org.dspace.curate.XmlWorkflowCuratorServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dspace-api Show documentation
Show all versions of dspace-api Show documentation
DSpace core data model and service APIs.
/**
* 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.curate;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Context;
import org.dspace.core.LogHelper;
import org.dspace.curate.service.XmlWorkflowCuratorService;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.GroupService;
import org.dspace.services.ConfigurationService;
import org.dspace.workflow.CurationTaskConfig;
import org.dspace.workflow.FlowStep;
import org.dspace.workflow.Task;
import org.dspace.workflow.TaskSet;
import org.dspace.xmlworkflow.RoleMembers;
import org.dspace.xmlworkflow.WorkflowConfigurationException;
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
import org.dspace.xmlworkflow.service.XmlWorkflowService;
import org.dspace.xmlworkflow.state.Step;
import org.dspace.xmlworkflow.state.Workflow;
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService;
import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Manage interactions between curation and workflow. A curation task can be
* attached to a workflow step, to be executed during the step.
*
* @see CurationTaskConfig
* @author mwood
*/
@Service
public class XmlWorkflowCuratorServiceImpl
implements XmlWorkflowCuratorService {
private static final Logger LOG
= org.apache.logging.log4j.LogManager.getLogger();
@Autowired(required = true)
protected XmlWorkflowFactory workflowFactory;
@Autowired(required = true)
protected ConfigurationService configurationService;
@Autowired(required = true)
protected GroupService groupService;
@Autowired(required = true)
protected EPersonService ePersonService;
@Autowired(required = true)
protected CollectionService collectionService;
@Autowired(required = true)
protected ClaimedTaskService claimedTaskService;
@Autowired(required = true)
protected CurationTaskConfig curationTaskConfig;
@Autowired(required = true)
protected XmlWorkflowService workflowService;
@Autowired(required = true)
protected XmlWorkflowItemService workflowItemService;
/** A sink for curation task reports. */
private final StringBuilder reporter = new StringBuilder();
@Override
public boolean needsCuration(Context c, XmlWorkflowItem wfi)
throws SQLException, IOException {
return getFlowStep(c, wfi) != null;
}
@Override
public boolean doCuration(Context c, XmlWorkflowItem wfi)
throws AuthorizeException, IOException, SQLException {
Curator curator = new Curator();
curator.setReporter(reporter);
return curate(curator, c, wfi);
}
@Override
public boolean curate(Curator curator, Context c, String wfId)
throws AuthorizeException, IOException, SQLException {
XmlWorkflowItem wfi = workflowItemService.find(c, Integer.parseInt(wfId));
if (wfi != null) {
return curate(curator, c, wfi);
} else {
LOG.warn(LogHelper.getHeader(c, "No workflow item found for id: {}", null), wfId);
}
return false;
}
@Override
public boolean curate(Curator curator, Context c, XmlWorkflowItem wfi)
throws AuthorizeException, IOException, SQLException {
FlowStep step = getFlowStep(c, wfi);
if (step != null) {
// assign collection to item in case task needs it
Item item = wfi.getItem();
item.setOwningCollection(wfi.getCollection());
for (Task task : step.tasks) {
curator.addTask(task.name);
curator.curate(item);
int status = curator.getStatus(task.name);
String result = curator.getResult(task.name);
String action = "none";
switch (status) {
case Curator.CURATE_FAIL:
// task failed - notify any contacts the task has assigned
if (task.powers.contains("reject")) {
action = "reject";
}
notifyContacts(c, wfi, task, "fail", action, result);
// if task so empowered, reject submission and terminate
if ("reject".equals(action)) {
workflowService.sendWorkflowItemBackSubmission(c, wfi,
c.getCurrentUser(), null,
task.name + ": " + result);
return false;
}
break;
case Curator.CURATE_SUCCESS:
if (task.powers.contains("approve")) {
action = "approve";
}
notifyContacts(c, wfi, task, "success", action, result);
if ("approve".equals(action)) {
// cease further task processing and advance submission
return true;
}
break;
case Curator.CURATE_ERROR:
notifyContacts(c, wfi, task, "error", action, result);
break;
default:
break;
}
curator.clear();
}
// Record any reporting done by the tasks.
if (reporter.length() > 0) {
LOG.info("Curation tasks over item {} for step {} report:%n{}",
() -> wfi.getItem().getID(),
() -> step.step,
() -> reporter.toString());
}
}
return true;
}
/**
* Find the flow step occupied by a work flow item.
* @param c session context.
* @param wfi the work flow item in question.
* @return the current flow step for the item, or null.
* @throws SQLException
* @throws IOException
*/
protected FlowStep getFlowStep(Context c, XmlWorkflowItem wfi)
throws SQLException, IOException {
if (claimedTaskService.find(c, wfi).isEmpty()) { // No claimed tasks: assume first step
Collection coll = wfi.getCollection();
String taskSetName = curationTaskConfig.containsKey(coll.getHandle()) ?
coll.getHandle() : CurationTaskConfig.DEFAULT_TASKSET_NAME;
TaskSet ts = curationTaskConfig.findTaskSet(taskSetName);
return ts.steps.isEmpty() ? null : ts.steps.get(0);
}
ClaimedTask claimedTask
= claimedTaskService.findByWorkflowIdAndEPerson(c, wfi, c.getCurrentUser());
if (claimedTask != null) {
Collection coll = wfi.getCollection();
String taskSetName = curationTaskConfig.containsKey(coll.getHandle()) ?
coll.getHandle() : CurationTaskConfig.DEFAULT_TASKSET_NAME;
TaskSet ts = curationTaskConfig.findTaskSet(taskSetName);
for (FlowStep fstep : ts.steps) {
if (fstep.step.equals(claimedTask.getStepID())) {
return fstep;
}
}
}
return null;
}
/**
* Send email to people who should be notified when curation tasks are run.
*
* @param c session context.
* @param wfi the work flow item being curated.
* @param task the curation task being applied.
* @param status status returned by the task.
* @param action action to be taken as a result of task status.
* @param message anything the code wants to say about the task run.
* @throws AuthorizeException passed through.
* @throws IOException passed through.
* @throws SQLException passed through.
*/
protected void notifyContacts(Context c, XmlWorkflowItem wfi,
Task task,
String status, String action, String message)
throws AuthorizeException, IOException, SQLException {
List epa = resolveContacts(c, task.getContacts(status), wfi);
if (epa.size() > 0) {
workflowService.notifyOfCuration(c, wfi, epa, task.name, action, message);
}
}
/**
* Develop a list of EPerson from a list of perhaps symbolic "contact" names.
*
* @param c session context.
* @param contacts the list of concrete and symbolic groups to resolve.
* @param wfi the work flow item associated with these groups via its current work flow step.
* @return the EPersons associated with the current state of {@code wfi}
* @throws AuthorizeException passed through.
* @throws IOException passed through.
* @throws SQLException passed through.
*/
protected List resolveContacts(Context c, List contacts,
XmlWorkflowItem wfi)
throws AuthorizeException, IOException, SQLException {
List epList = new ArrayList<>();
for (String contact : contacts) {
// decode contacts
if ("$flowgroup".equals(contact)) {
// special literal for current flowgoup
ClaimedTask claimedTask = claimedTaskService.findByWorkflowIdAndEPerson(c, wfi, c.getCurrentUser());
String stepID = claimedTask.getStepID();
Step step;
try {
Workflow workflow = workflowFactory.getWorkflow(wfi.getCollection());
step = workflow.getStep(stepID);
} catch (WorkflowConfigurationException e) {
LOG.error("Failed to locate current workflow step for workflow item {}",
String.valueOf(wfi.getID()), e);
return epList;
}
RoleMembers roleMembers = step.getRole().getMembers(c, wfi);
for (EPerson ep : roleMembers.getEPersons()) {
epList.add(ep);
}
for (Group group : roleMembers.getGroups()) {
epList.addAll(group.getMembers());
}
} else if ("$colladmin".equals(contact)) {
Group adGroup = wfi.getCollection().getAdministrators();
if (adGroup != null) {
epList.addAll(groupService.allMembers(c, adGroup));
}
} else if ("$siteadmin".equals(contact)) {
EPerson siteEp = ePersonService.findByEmail(c,
configurationService.getProperty("mail.admin"));
if (siteEp != null) {
epList.add(siteEp);
}
} else if (contact.indexOf("@") > 0) {
// little shaky heuristic here - assume an eperson email name
EPerson ep = ePersonService.findByEmail(c, contact);
if (ep != null) {
epList.add(ep);
}
} else {
// assume it is an arbitrary group name
Group group = groupService.findByName(c, contact);
if (group != null) {
epList.addAll(groupService.allMembers(c, group));
}
}
}
return epList;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy