mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-18 07:23:08 +00:00
- Merged with KevinVdV/DSpace/DS-4239-migrate-workflow-xml-to-spring
- Changed all implementations of XmlWorkflowFactoryImpl to work with new mapping - Moved their java doc to XmlWorkflowFactory - Removed/Changed exceptions - Altered tests in WorkflowDefinitionRestRepositoryIT to work with changes Merge remote-tracking branch 'github-kevin/DS-4239-migrate-workflow-xml-to-spring' into workflow-step-definitions # Conflicts: # dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowFactoryImpl.java # dspace-api/src/main/java/org/dspace/xmlworkflow/factory/XmlWorkflowFactory.java
This commit is contained in:
@@ -48,6 +48,7 @@ import org.dspace.harvest.HarvestedCollection;
|
|||||||
import org.dspace.harvest.service.HarvestedCollectionService;
|
import org.dspace.harvest.service.HarvestedCollectionService;
|
||||||
import org.dspace.workflow.factory.WorkflowServiceFactory;
|
import org.dspace.workflow.factory.WorkflowServiceFactory;
|
||||||
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
||||||
|
import org.dspace.xmlworkflow.XmlWorkflowFactoryImpl;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
|
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
|
||||||
import org.dspace.xmlworkflow.state.Workflow;
|
import org.dspace.xmlworkflow.state.Workflow;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
|
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
|
||||||
@@ -383,7 +384,7 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl<Collection> i
|
|||||||
log.error(LogManager.getHeader(context, "setWorkflowGroup",
|
log.error(LogManager.getHeader(context, "setWorkflowGroup",
|
||||||
"collection_id=" + collection.getID() + " " + e.getMessage()), e);
|
"collection_id=" + collection.getID() + " " + e.getMessage()), e);
|
||||||
}
|
}
|
||||||
if (!StringUtils.equals(XmlWorkflowFactory.LEGACY_WORKFLOW_NAME, workflow.getID())) {
|
if (!StringUtils.equals(XmlWorkflowFactoryImpl.LEGACY_WORKFLOW_NAME, workflow.getID())) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"setWorkflowGroup can be used only on collection with the default basic dspace workflow. "
|
"setWorkflowGroup can be used only on collection with the default basic dspace workflow. "
|
||||||
+ "Instead, the collection: "
|
+ "Instead, the collection: "
|
||||||
|
@@ -13,14 +13,15 @@ import java.util.List;
|
|||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
|
||||||
import org.dspace.eperson.service.GroupService;
|
import org.dspace.eperson.service.GroupService;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
|
||||||
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
|
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.WorkflowItemRole;
|
import org.dspace.xmlworkflow.storedcomponents.WorkflowItemRole;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.service.CollectionRoleService;
|
import org.dspace.xmlworkflow.storedcomponents.service.CollectionRoleService;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.service.WorkflowItemRoleService;
|
import org.dspace.xmlworkflow.storedcomponents.service.WorkflowItemRoleService;
|
||||||
|
import org.springframework.beans.factory.BeanNameAware;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Required;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The role that is responsible for a certain step
|
* The role that is responsible for a certain step
|
||||||
@@ -32,38 +33,36 @@ import org.dspace.xmlworkflow.storedcomponents.service.WorkflowItemRoleService;
|
|||||||
* @author Ben Bosman (ben at atmire dot com)
|
* @author Ben Bosman (ben at atmire dot com)
|
||||||
* @author Mark Diggory (markd at atmire dot com)
|
* @author Mark Diggory (markd at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public class Role {
|
public class Role implements BeanNameAware {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GroupService groupService;
|
||||||
|
@Autowired
|
||||||
|
private CollectionRoleService collectionRoleService;
|
||||||
|
@Autowired
|
||||||
|
private WorkflowItemRoleService workflowItemRoleService;
|
||||||
|
|
||||||
private GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
|
|
||||||
private CollectionRoleService collectionRoleService = XmlWorkflowServiceFactory.getInstance()
|
|
||||||
.getCollectionRoleService();
|
|
||||||
private WorkflowItemRoleService workflowItemRoleService = XmlWorkflowServiceFactory.getInstance()
|
|
||||||
.getWorkflowItemRoleService();
|
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
private boolean isInternal;
|
private boolean isInternal = false;
|
||||||
private Scope scope;
|
private Scope scope = Scope.COLLECTION;
|
||||||
|
|
||||||
public static enum Scope {
|
@Override
|
||||||
|
public void setBeanName(String s) {
|
||||||
|
this.id = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Scope {
|
||||||
REPOSITORY,
|
REPOSITORY,
|
||||||
COLLECTION,
|
COLLECTION,
|
||||||
ITEM
|
ITEM
|
||||||
}
|
}
|
||||||
|
|
||||||
public Role(String id, String name, String description, boolean isInternal, Scope scope) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.description = description;
|
|
||||||
this.isInternal = isInternal;
|
|
||||||
this.scope = scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -118,4 +117,41 @@ public class Role {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name specified in the name attribute of a role will be used to lookup the in DSpace.
|
||||||
|
* The lookup will depend on the scope specified in the "scope" attribute:
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the description of the role
|
||||||
|
* @param description the description
|
||||||
|
*/
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the scope attribute, depending on the scope the users will be retrieved in the following manner:
|
||||||
|
* * collection: The collection value specifies that the group will be configured at the level of the collection.
|
||||||
|
* * repository: The repository scope uses groups that are defined at repository level in DSpace.
|
||||||
|
* item: The item scope assumes that a different action in the workflow will assign a number of EPersons or
|
||||||
|
* Groups to a specific workflow-item in order to perform a step.
|
||||||
|
* @param scope the scope parameter
|
||||||
|
*/
|
||||||
|
public void setScope(Scope scope) {
|
||||||
|
this.scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional attribute which isn't really used at the moment, false by default
|
||||||
|
* @param internal if the role is internal
|
||||||
|
*/
|
||||||
|
public void setInternal(boolean internal) {
|
||||||
|
isInternal = internal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,8 +13,8 @@ import java.io.StringWriter;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -236,13 +236,13 @@ public class WorkflowUtils extends Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static HashMap<String, Role> getCollectionRoles(Collection thisCollection)
|
public static Map<String, Role> getCollectionRoles(Collection thisCollection)
|
||||||
throws IOException, WorkflowConfigurationException, SQLException {
|
throws IOException, WorkflowConfigurationException, SQLException {
|
||||||
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
|
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
|
||||||
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
|
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
|
||||||
if (workflow != null) {
|
if (workflow != null) {
|
||||||
//Make sure we find one
|
//Make sure we find one
|
||||||
HashMap<String, Role> allRoles = workflow.getRoles();
|
Map<String, Role> allRoles = workflow.getRoles();
|
||||||
//We have retrieved all our roles, not get the ones which can be configured by the collection
|
//We have retrieved all our roles, not get the ones which can be configured by the collection
|
||||||
for (String roleId : allRoles.keySet()) {
|
for (String roleId : allRoles.keySet()) {
|
||||||
Role role = allRoles.get(roleId);
|
Role role = allRoles.get(roleId);
|
||||||
@@ -257,13 +257,13 @@ public class WorkflowUtils extends Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static HashMap<String, Role> getCollectionAndRepositoryRoles(Collection thisCollection)
|
public static Map<String, Role> getCollectionAndRepositoryRoles(Collection thisCollection)
|
||||||
throws IOException, WorkflowConfigurationException, SQLException {
|
throws IOException, WorkflowConfigurationException, SQLException {
|
||||||
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
|
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
|
||||||
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
|
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
|
||||||
if (workflow != null) {
|
if (workflow != null) {
|
||||||
//Make sure we find one
|
//Make sure we find one
|
||||||
HashMap<String, Role> allRoles = workflow.getRoles();
|
Map<String, Role> allRoles = workflow.getRoles();
|
||||||
//We have retrieved all our roles, not get the ones which can be configured by the collection
|
//We have retrieved all our roles, not get the ones which can be configured by the collection
|
||||||
for (String roleId : allRoles.keySet()) {
|
for (String roleId : allRoles.keySet()) {
|
||||||
Role role = allRoles.get(roleId);
|
Role role = allRoles.get(roleId);
|
||||||
@@ -279,13 +279,13 @@ public class WorkflowUtils extends Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static HashMap<String, Role> getAllExternalRoles(Collection thisCollection)
|
public static Map<String, Role> getAllExternalRoles(Collection thisCollection)
|
||||||
throws IOException, WorkflowConfigurationException, SQLException {
|
throws IOException, WorkflowConfigurationException, SQLException {
|
||||||
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
|
Workflow workflow = xmlWorkflowFactory.getWorkflow(thisCollection);
|
||||||
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
|
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
|
||||||
if (workflow != null) {
|
if (workflow != null) {
|
||||||
//Make sure we find one
|
//Make sure we find one
|
||||||
HashMap<String, Role> allRoles = workflow.getRoles();
|
Map<String, Role> allRoles = workflow.getRoles();
|
||||||
//We have retrieved all our roles, not get the ones which can be configured by the collection
|
//We have retrieved all our roles, not get the ones which can be configured by the collection
|
||||||
for (String roleId : allRoles.keySet()) {
|
for (String roleId : allRoles.keySet()) {
|
||||||
Role role = allRoles.get(roleId);
|
Role role = allRoles.get(roleId);
|
||||||
|
@@ -7,31 +7,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.xmlworkflow;
|
package org.dspace.xmlworkflow;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.xpath.XPathAPI;
|
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.services.ConfigurationService;
|
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
|
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
|
||||||
import org.dspace.xmlworkflow.state.Workflow;
|
import org.dspace.xmlworkflow.state.Workflow;
|
||||||
import org.dspace.xmlworkflow.state.actions.UserSelectionActionConfig;
|
import org.springframework.beans.factory.annotation.Required;
|
||||||
import org.dspace.xmlworkflow.state.actions.WorkflowActionConfig;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The workflowfactory is responsible for parsing the
|
* The workflowfactory is responsible for parsing the
|
||||||
@@ -46,243 +30,81 @@ import org.w3c.dom.NodeList;
|
|||||||
*/
|
*/
|
||||||
public class XmlWorkflowFactoryImpl implements XmlWorkflowFactory {
|
public class XmlWorkflowFactoryImpl implements XmlWorkflowFactory {
|
||||||
|
|
||||||
|
public static final String LEGACY_WORKFLOW_NAME = "defaultWorkflow";
|
||||||
|
|
||||||
private Logger log = org.apache.logging.log4j.LogManager.getLogger(XmlWorkflowFactoryImpl.class);
|
private Logger log = org.apache.logging.log4j.LogManager.getLogger(XmlWorkflowFactoryImpl.class);
|
||||||
|
|
||||||
@Autowired(required = true)
|
private Map<String, Workflow> workflowMapping;
|
||||||
protected ConfigurationService configurationService;
|
|
||||||
protected HashMap<String, Workflow> collectionHandleToWorkflowCache;
|
|
||||||
protected HashMap<String, Workflow> workflowNameToWorkflowCache;
|
|
||||||
protected List<Workflow> workflowCache;
|
|
||||||
protected HashMap<String, List<String>> workflowNameToCollectionHandlesCache;
|
|
||||||
protected String path;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
protected void init() {
|
|
||||||
path = configurationService
|
|
||||||
.getProperty("dspace.dir") + File.separator + "config" + File.separator + "workflow.xml";
|
|
||||||
}
|
|
||||||
// private static String pathActions = ConfigurationManager.getProperty("dspace.dir")+"/config/workflow-actions.xml";
|
|
||||||
|
|
||||||
protected XmlWorkflowFactoryImpl() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Workflow getWorkflow(Collection collection) throws WorkflowConfigurationException {
|
public Workflow getWorkflow(Collection collection) throws WorkflowConfigurationException {
|
||||||
return this.getWorkflowById(collectionHandleToWorkflowCache, collection.getHandle(), "collection");
|
// Attempt to retrieve our workflow object
|
||||||
|
if (workflowMapping.get(collection.getHandle()) == null) {
|
||||||
|
final Workflow defaultWorkflow = workflowMapping.get(LEGACY_WORKFLOW_NAME);
|
||||||
|
if (defaultWorkflow != null) {
|
||||||
|
return defaultWorkflow;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return workflowMapping.get(collection.getHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new WorkflowConfigurationException(
|
||||||
|
"Error while retrieving workflow for the following collection: " + collection.getHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Required
|
||||||
|
public void setWorkflowMapping(Map<String, Workflow> workflowMapping) {
|
||||||
|
this.workflowMapping = workflowMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Workflow getWorkflowByName(String workflowName) throws WorkflowConfigurationException {
|
public Workflow getWorkflowByName(String workflowName) throws WorkflowConfigurationException {
|
||||||
return this.getWorkflowById(workflowNameToWorkflowCache, workflowName, "workflow");
|
for (Workflow workflow : workflowMapping.values()) {
|
||||||
}
|
if (workflow.getID().equals(workflowName)) {
|
||||||
|
return workflow;
|
||||||
/**
|
|
||||||
* Tries to retrieve a workflow from the given cache by the given id, if it is not present it tries to resolve the
|
|
||||||
* id to a workflow from the workflow.xml at path (by using the workflow-map with given xpathId)
|
|
||||||
* If it gets resolved this mapping gets added to the given cache and the resolved workflow returned
|
|
||||||
* If it can't be resolved, the default mapping gets returned (and added to cache if not already present)
|
|
||||||
*
|
|
||||||
* @param cache Cache we are using for the id-workflow mapping
|
|
||||||
* @param id Id we're trying to resolve to a workflow
|
|
||||||
* @param xpathId XpathId used to resolve the id to a workflow if it wasn't present in the cache
|
|
||||||
* @return Corresponding workflow mapped to the given id
|
|
||||||
* @throws WorkflowConfigurationException If no corresponding mapping or default can be found or error trying to
|
|
||||||
* to resolve to one
|
|
||||||
*/
|
|
||||||
private Workflow getWorkflowById(HashMap<String, Workflow> cache, String id, String xpathId)
|
|
||||||
throws WorkflowConfigurationException {
|
|
||||||
//Initialize our cache if we have none
|
|
||||||
if (cache == null) {
|
|
||||||
cache = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to retrieve our workflow object
|
|
||||||
if (cache.get(id) == null) {
|
|
||||||
try {
|
|
||||||
// No workflow cache found for the id, check if we have a workflowId for this id
|
|
||||||
File xmlFile = new File(path);
|
|
||||||
Document input = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
|
|
||||||
Node mainNode = input.getFirstChild();
|
|
||||||
Node workflowMap = XPathAPI.selectSingleNode(mainNode,
|
|
||||||
"//workflow-map/name-map[@" + xpathId + "='" + id + "']");
|
|
||||||
if (workflowMap == null && xpathId != "workflow") {
|
|
||||||
// No workflowId found by this id in cache, so retrieve & use the default workflow
|
|
||||||
if (cache.get("default") == null) {
|
|
||||||
Workflow defaultWorkflow = this.getDefaultWorkflow();
|
|
||||||
cache.put("default", defaultWorkflow);
|
|
||||||
cache.put(id, defaultWorkflow);
|
|
||||||
return defaultWorkflow;
|
|
||||||
} else {
|
|
||||||
return cache.get("default");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// We have a workflowID so retrieve it & resolve it to a workflow, also store it in our cache
|
|
||||||
String workflowID = "";
|
|
||||||
if (xpathId.equalsIgnoreCase("workflow")) {
|
|
||||||
workflowID = id;
|
|
||||||
} else {
|
|
||||||
workflowID = workflowMap.getAttributes().getNamedItem("workflow").getTextContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node workflowNode = XPathAPI.selectSingleNode(mainNode, "//workflow[@id='" + workflowID + "']");
|
|
||||||
Workflow wf = new Workflow(workflowID, getRoles(workflowNode));
|
|
||||||
Step step = createFirstStep(wf, workflowNode);
|
|
||||||
wf.setFirstStep(step);
|
|
||||||
cache.put(id, wf);
|
|
||||||
return wf;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error while retrieving workflow mapping of " + xpathId + ": " + id, e);
|
|
||||||
throw new WorkflowConfigurationException(
|
|
||||||
"Error while retrieving workflow mapping of " + xpathId + ": " + id);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return cache.get(id);
|
|
||||||
}
|
}
|
||||||
|
throw new WorkflowConfigurationException(
|
||||||
|
"Error while retrieving workflow by the following name: " + workflowName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the default workflow, i.e. the workflow that is mapped to collection=default in workflow.xml
|
|
||||||
*/
|
|
||||||
public Workflow getDefaultWorkflow() throws WorkflowConfigurationException {
|
|
||||||
//Initialize our cache if we have none
|
|
||||||
if (collectionHandleToWorkflowCache == null) {
|
|
||||||
collectionHandleToWorkflowCache = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
//attempt to retrieve default workflow
|
|
||||||
if (collectionHandleToWorkflowCache.get("default") == null) {
|
|
||||||
try {
|
|
||||||
File xmlFile = new File(path);
|
|
||||||
Document input = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
|
|
||||||
Node mainNode = input.getFirstChild();
|
|
||||||
String workflowID = XPathAPI
|
|
||||||
.selectSingleNode(mainNode, "//workflow-map/name-map[@collection='default']")
|
|
||||||
.getAttributes().getNamedItem("workflow").getTextContent();
|
|
||||||
if (workflowID == null) {
|
|
||||||
throw new WorkflowConfigurationException("No default workflow mapping is present");
|
|
||||||
}
|
|
||||||
Node workflowNode = XPathAPI.selectSingleNode(mainNode, "//workflow[@id='" + workflowID + "']");
|
|
||||||
Workflow wf = new Workflow(workflowID, getRoles(workflowNode));
|
|
||||||
Step step = createFirstStep(wf, workflowNode);
|
|
||||||
wf.setFirstStep(step);
|
|
||||||
return wf;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error while retrieve default workflow", e);
|
|
||||||
throw new WorkflowConfigurationException("Error while retrieve default workflow");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return collectionHandleToWorkflowCache.get("default");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of all configured workflows, or returns the cache of this if it was already created
|
|
||||||
*
|
|
||||||
* @return List of all configured workflows
|
|
||||||
* @throws WorkflowConfigurationException
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<Workflow> getAllConfiguredWorkflows() throws WorkflowConfigurationException {
|
public Workflow getDefaultWorkflow() {
|
||||||
// Initialize our cache if we have none
|
return this.workflowMapping.get(LEGACY_WORKFLOW_NAME);
|
||||||
if (workflowCache == null || workflowCache.size() == 0) {
|
|
||||||
workflowCache = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
// No workflow cache found; create it
|
|
||||||
File xmlFile = new File(path);
|
|
||||||
Document input = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
|
|
||||||
Node mainNode = input.getFirstChild();
|
|
||||||
NodeList allWorkflowNodes = XPathAPI.selectNodeList(mainNode, "//workflow");
|
|
||||||
for (int i = 0; i < allWorkflowNodes.getLength(); i++) {
|
|
||||||
String workflowID =
|
|
||||||
allWorkflowNodes.item(i).getAttributes().getNamedItem("id").getTextContent();
|
|
||||||
Node workflowNode = XPathAPI.selectSingleNode(mainNode, "//workflow[@id='" + workflowID + "']");
|
|
||||||
Workflow wf = new Workflow(workflowID, getRoles(workflowNode));
|
|
||||||
Step step = createFirstStep(wf, workflowNode);
|
|
||||||
wf.setFirstStep(step);
|
|
||||||
workflowCache.add(wf);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error while creating list of all configure workflows");
|
|
||||||
throw new WorkflowConfigurationException("Error while creating list of all configure workflows");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return workflowCache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a list of collections handles that are mapped to the given workflow in the workflow configuration.
|
|
||||||
* Makes use of a cache so it only retrieves the workflowName->List<collectionHandle> if it's not cached
|
|
||||||
*
|
|
||||||
* @param workflowName Name of workflow we want the collections of that are mapped to is
|
|
||||||
* @return List of collection handles mapped to the requested workflow
|
|
||||||
* @throws WorkflowConfigurationException
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getCollectionHandlesMappedToWorklow(String workflowName) throws WorkflowConfigurationException {
|
public List<Workflow> getAllConfiguredWorkflows() {
|
||||||
// Initialize our cache if we have none
|
return new ArrayList<>(this.workflowMapping.values());
|
||||||
if (workflowNameToCollectionHandlesCache == null) {
|
|
||||||
workflowNameToCollectionHandlesCache = new HashMap<>();
|
|
||||||
}
|
|
||||||
// Attempt to retrieve the corresponding collections
|
|
||||||
if (workflowNameToCollectionHandlesCache.get(workflowName) == null) {
|
|
||||||
try {
|
|
||||||
// No collections cached for this workflow, create it
|
|
||||||
File xmlFile = new File(path);
|
|
||||||
Document input = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
|
|
||||||
Node mainNode = input.getFirstChild();
|
|
||||||
NodeList allWorkflowNodes = XPathAPI.selectNodeList(mainNode, "//workflow-map/name-map" +
|
|
||||||
"[@workflow='" + workflowName + "']");
|
|
||||||
List<String> collectionsHandlesMappedToThisWorkflow = new ArrayList<>();
|
|
||||||
for (int i = 0; i < allWorkflowNodes.getLength(); i++) {
|
|
||||||
String collectionHandle =
|
|
||||||
allWorkflowNodes.item(i).getAttributes().getNamedItem("collection").getTextContent();
|
|
||||||
collectionsHandlesMappedToThisWorkflow.add(collectionHandle);
|
|
||||||
}
|
|
||||||
workflowNameToCollectionHandlesCache.put(workflowName, collectionsHandlesMappedToThisWorkflow);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error while getting collections mapped to this workflow: " + workflowName);
|
|
||||||
throw new WorkflowConfigurationException(
|
|
||||||
"Error while getting collections mapped to this workflow: " + workflowName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (workflowNameToCollectionHandlesCache.get(workflowName) != null) {
|
|
||||||
return workflowNameToCollectionHandlesCache.get(workflowName);
|
|
||||||
} else {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check to see if there is a workflow configured by the given name
|
|
||||||
*
|
|
||||||
* @param workflowName Name of a possible configured workflow
|
|
||||||
* @return True if there is a workflow configured by this name, false otherwise
|
|
||||||
* @throws WorkflowConfigurationException
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean workflowByThisNameExists(String workflowName) throws WorkflowConfigurationException {
|
public List<String> getCollectionHandlesMappedToWorklow(String workflowName) {
|
||||||
List<Workflow> allConfiguredWorkflows = this.getAllConfiguredWorkflows();
|
List<String> collectionsMapped = new ArrayList<>();
|
||||||
for (Workflow workflow : allConfiguredWorkflows) {
|
for (String handle : this.workflowMapping.keySet()) {
|
||||||
if (workflow.getID().equalsIgnoreCase(workflowName)) {
|
if (this.workflowMapping.get(handle).getID().equals(workflowName)) {
|
||||||
|
collectionsMapped.add(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collectionsMapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean workflowByThisNameExists(String workflowName) {
|
||||||
|
for (Workflow workflow : this.workflowMapping.values()) {
|
||||||
|
if (workflow.getID().equals(workflowName)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check to see if the given workflowName is the workflow configured to be default for collections
|
@Override
|
||||||
* @param workflowName Name of workflow to check if default
|
|
||||||
* @return True if given workflowName is the workflow mapped to default for collections, otherwise false
|
|
||||||
* @throws WorkflowConfigurationException
|
|
||||||
*/
|
|
||||||
public boolean isDefaultWorkflow(String workflowName) throws WorkflowConfigurationException {
|
public boolean isDefaultWorkflow(String workflowName) throws WorkflowConfigurationException {
|
||||||
try {
|
try {
|
||||||
Workflow defaultWorkflow = this.getDefaultWorkflow();
|
Workflow defaultWorkflow = this.getDefaultWorkflow();
|
||||||
return (defaultWorkflow.getID().equalsIgnoreCase(workflowName));
|
return (defaultWorkflow.getID().equals(workflowName));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Error while trying to check if " + workflowName + " is the default workflow", e);
|
log.error("Error while trying to check if " + workflowName + " is the default workflow", e);
|
||||||
throw new WorkflowConfigurationException("Error while trying to check if " + workflowName
|
throw new WorkflowConfigurationException("Error while trying to check if " + workflowName
|
||||||
@@ -291,161 +113,4 @@ public class XmlWorkflowFactoryImpl implements XmlWorkflowFactory {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Step createFirstStep(Workflow workflow, Node workflowNode)
|
|
||||||
throws TransformerException, WorkflowConfigurationException {
|
|
||||||
String firstStepID = workflowNode.getAttributes().getNamedItem("start").getTextContent();
|
|
||||||
Node stepNode = XPathAPI.selectSingleNode(workflowNode, "step[@id='" + firstStepID + "']");
|
|
||||||
if (stepNode == null) {
|
|
||||||
throw new WorkflowConfigurationException(
|
|
||||||
"First step does not exist for workflow: " + workflowNode.getAttributes().getNamedItem("id")
|
|
||||||
.getTextContent());
|
|
||||||
}
|
|
||||||
Node roleNode = stepNode.getAttributes().getNamedItem("role");
|
|
||||||
Role role = null;
|
|
||||||
if (roleNode != null) {
|
|
||||||
role = workflow.getRoles().get(roleNode.getTextContent());
|
|
||||||
}
|
|
||||||
String userSelectionActionID = stepNode.getAttributes().getNamedItem("userSelectionMethod").getTextContent();
|
|
||||||
UserSelectionActionConfig userSelection = createUserAssignmentActionConfig(userSelectionActionID);
|
|
||||||
return new Step(firstStepID, workflow, role, userSelection, getStepActionConfigs(stepNode),
|
|
||||||
getStepOutcomes(stepNode), getNbRequiredUser(stepNode));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected Map<Integer, String> getStepOutcomes(Node stepNode)
|
|
||||||
throws TransformerException, WorkflowConfigurationException {
|
|
||||||
try {
|
|
||||||
NodeList outcomesNodeList = XPathAPI.selectNodeList(stepNode, "outcomes/step");
|
|
||||||
Map<Integer, String> outcomes = new HashMap<Integer, String>();
|
|
||||||
//Add our outcome, should it be null it will be interpreted as the end of the line (last step)
|
|
||||||
for (int i = 0; i < outcomesNodeList.getLength(); i++) {
|
|
||||||
Node outcomeNode = outcomesNodeList.item(i);
|
|
||||||
int index = Integer.parseInt(outcomeNode.getAttributes().getNamedItem("status").getTextContent());
|
|
||||||
if (index < 0) {
|
|
||||||
throw new WorkflowConfigurationException(
|
|
||||||
"Outcome configuration error for step: " + stepNode.getAttributes().getNamedItem("id")
|
|
||||||
.getTextContent());
|
|
||||||
}
|
|
||||||
outcomes.put(index, outcomeNode.getTextContent());
|
|
||||||
}
|
|
||||||
return outcomes;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Outcome configuration error for step: " +
|
|
||||||
stepNode.getAttributes().getNamedItem("id").getTextContent(), e);
|
|
||||||
throw new WorkflowConfigurationException(
|
|
||||||
"Outcome configuration error for step: " + stepNode.getAttributes().getNamedItem("id")
|
|
||||||
.getTextContent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getNbRequiredUser(Node stepnode) {
|
|
||||||
if (stepnode.getAttributes().getNamedItem("requiredUsers") != null) {
|
|
||||||
return Integer.parseInt(stepnode.getAttributes().getNamedItem("requiredUsers").getTextContent());
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<String> getStepActionConfigs(Node stepNode) throws TransformerException {
|
|
||||||
NodeList actionConfigNodes = XPathAPI.selectNodeList(stepNode, "actions/action");
|
|
||||||
List<String> actionConfigIDs = new ArrayList<String>();
|
|
||||||
for (int i = 0; i < actionConfigNodes.getLength(); i++) {
|
|
||||||
actionConfigIDs.add(actionConfigNodes.item(i).getAttributes().getNamedItem("id").getTextContent());
|
|
||||||
}
|
|
||||||
return actionConfigIDs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Step createStep(Workflow workflow, String stepID) throws WorkflowConfigurationException, IOException {
|
|
||||||
try {
|
|
||||||
File xmlFile = new File(path);
|
|
||||||
Document input = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
|
|
||||||
Node mainNode = input.getFirstChild();
|
|
||||||
Node stepNode = XPathAPI.selectSingleNode(mainNode, "//workflow[@id='" + workflow.getID()
|
|
||||||
+ "']/step[@id='" + stepID + "']");
|
|
||||||
|
|
||||||
if (stepNode == null) {
|
|
||||||
throw new WorkflowConfigurationException("Step does not exist for workflow: " + workflow.getID());
|
|
||||||
}
|
|
||||||
Node roleNode = stepNode.getAttributes().getNamedItem("role");
|
|
||||||
Role role = null;
|
|
||||||
if (roleNode != null) {
|
|
||||||
role = workflow.getRoles().get(roleNode.getTextContent());
|
|
||||||
}
|
|
||||||
String userSelectionActionID = stepNode.getAttributes().getNamedItem("userSelectionMethod")
|
|
||||||
.getTextContent();
|
|
||||||
UserSelectionActionConfig userSelection = createUserAssignmentActionConfig(userSelectionActionID);
|
|
||||||
return new Step(stepID, workflow, role, userSelection, getStepActionConfigs(stepNode),
|
|
||||||
getStepOutcomes(stepNode), getNbRequiredUser(stepNode));
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error while creating step with :" + stepID, e);
|
|
||||||
throw new WorkflowConfigurationException(
|
|
||||||
"Step: " + stepID + " does not exist for workflow: " + workflow.getID());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected UserSelectionActionConfig createUserAssignmentActionConfig(String userSelectionActionID) {
|
|
||||||
return DSpaceServicesFactory.getInstance().getServiceManager()
|
|
||||||
.getServiceByName(userSelectionActionID, UserSelectionActionConfig.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WorkflowActionConfig createWorkflowActionConfig(String actionID) {
|
|
||||||
return DSpaceServicesFactory.getInstance().getServiceManager()
|
|
||||||
.getServiceByName(actionID, WorkflowActionConfig.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected LinkedHashMap<String, Role> getRoles(Node workflowNode) throws WorkflowConfigurationException {
|
|
||||||
NodeList roleNodes = null;
|
|
||||||
try {
|
|
||||||
roleNodes = XPathAPI.selectNodeList(workflowNode, "roles/role");
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error while resolving nodes", e);
|
|
||||||
throw new WorkflowConfigurationException("Error while retrieving roles");
|
|
||||||
}
|
|
||||||
LinkedHashMap<String, Role> roles = new LinkedHashMap<String, Role>();
|
|
||||||
for (int i = 0; i < roleNodes.getLength(); i++) {
|
|
||||||
String roleID = roleNodes.item(i).getAttributes().getNamedItem("id").getTextContent();
|
|
||||||
String roleName = roleNodes.item(i).getAttributes().getNamedItem("name").getTextContent();
|
|
||||||
Node descriptionNode = roleNodes.item(i).getAttributes().getNamedItem("description");
|
|
||||||
String roleDescription = null;
|
|
||||||
if (descriptionNode != null) {
|
|
||||||
roleDescription = descriptionNode.getTextContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node scopeNode = roleNodes.item(i).getAttributes().getNamedItem("scope");
|
|
||||||
String roleScope = null;
|
|
||||||
if (scopeNode != null) {
|
|
||||||
roleScope = scopeNode.getTextContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node internalNode = roleNodes.item(i).getAttributes().getNamedItem("internal");
|
|
||||||
String roleInternal;
|
|
||||||
boolean internal = false;
|
|
||||||
if (internalNode != null) {
|
|
||||||
roleInternal = internalNode.getTextContent();
|
|
||||||
internal = Boolean.parseBoolean(roleInternal);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Role.Scope scope;
|
|
||||||
if (roleScope == null || roleScope.equalsIgnoreCase("collection")) {
|
|
||||||
scope = Role.Scope.COLLECTION;
|
|
||||||
} else if (roleScope.equalsIgnoreCase("item")) {
|
|
||||||
scope = Role.Scope.ITEM;
|
|
||||||
} else if (roleScope.equalsIgnoreCase("repository")) {
|
|
||||||
scope = Role.Scope.REPOSITORY;
|
|
||||||
} else {
|
|
||||||
throw new WorkflowConfigurationException(
|
|
||||||
"An invalid role scope has been specified it must either be item or collection.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Role role = new Role(roleID, roleName, roleDescription, internal, scope);
|
|
||||||
roles.put(roleID, role);
|
|
||||||
}
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,14 +7,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.xmlworkflow.factory;
|
package org.dspace.xmlworkflow.factory;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
|
||||||
import org.dspace.xmlworkflow.state.Workflow;
|
import org.dspace.xmlworkflow.state.Workflow;
|
||||||
import org.dspace.xmlworkflow.state.actions.WorkflowActionConfig;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The xmlworkflowfactory is responsible for parsing the
|
* The xmlworkflowfactory is responsible for parsing the
|
||||||
@@ -31,21 +28,58 @@ public interface XmlWorkflowFactory {
|
|||||||
|
|
||||||
public final String LEGACY_WORKFLOW_NAME = "default";
|
public final String LEGACY_WORKFLOW_NAME = "default";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the workflow configuration for a single collection
|
||||||
|
*
|
||||||
|
* @param collection the collection for which we want our workflow
|
||||||
|
* @return the workflow configuration
|
||||||
|
* @throws WorkflowConfigurationException occurs if there is a configuration error in the workflow
|
||||||
|
*/
|
||||||
public Workflow getWorkflow(Collection collection) throws WorkflowConfigurationException;
|
public Workflow getWorkflow(Collection collection) throws WorkflowConfigurationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the workflow configuration by name
|
||||||
|
*
|
||||||
|
* @param workflowName the name for which we want our workflow
|
||||||
|
* @return the workflow configuration
|
||||||
|
* @throws WorkflowConfigurationException occurs if there is no workflow configured by that name
|
||||||
|
*/
|
||||||
public Workflow getWorkflowByName(String workflowName) throws WorkflowConfigurationException;
|
public Workflow getWorkflowByName(String workflowName) throws WorkflowConfigurationException;
|
||||||
|
|
||||||
public List<Workflow> getAllConfiguredWorkflows() throws WorkflowConfigurationException;
|
/**
|
||||||
|
* Creates a list of all configured workflows, or returns the cache of this if it was already created
|
||||||
|
*
|
||||||
|
* @return List of all configured workflows
|
||||||
|
*/
|
||||||
|
public List<Workflow> getAllConfiguredWorkflows();
|
||||||
|
|
||||||
public boolean workflowByThisNameExists(String workflowName) throws WorkflowConfigurationException;
|
/**
|
||||||
|
* Check to see if there is a workflow configured by the given name
|
||||||
|
*
|
||||||
|
* @param workflowName Name of a possible configured workflow
|
||||||
|
* @return True if there is a workflow configured by this name, false otherwise
|
||||||
|
* @throws WorkflowConfigurationException occurs if there is no workflow configured by that name
|
||||||
|
*/
|
||||||
|
public boolean workflowByThisNameExists(String workflowName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see if the given workflowName is the workflow configured to be default for collections
|
||||||
|
* @param workflowName Name of workflow to check if default
|
||||||
|
* @return True if given workflowName is the workflow mapped to default for collections, otherwise false
|
||||||
|
*/
|
||||||
public boolean isDefaultWorkflow(String workflowName) throws WorkflowConfigurationException;
|
public boolean isDefaultWorkflow(String workflowName) throws WorkflowConfigurationException;
|
||||||
|
|
||||||
public Workflow getDefaultWorkflow() throws WorkflowConfigurationException;
|
/**
|
||||||
|
* Gets the default workflow, i.e. the workflow that is mapped to collection=default in workflow.xml
|
||||||
|
*/
|
||||||
|
public Workflow getDefaultWorkflow();
|
||||||
|
|
||||||
public List<String> getCollectionHandlesMappedToWorklow(String workflowName) throws WorkflowConfigurationException;
|
/**
|
||||||
|
* Return a list of collections handles that are mapped to the given workflow in the workflow configuration.
|
||||||
public Step createStep(Workflow workflow, String stepID) throws WorkflowConfigurationException, IOException;
|
* Makes use of a cache so it only retrieves the workflowName->List<collectionHandle> if it's not cached
|
||||||
|
*
|
||||||
public WorkflowActionConfig createWorkflowActionConfig(String actionID);
|
* @param workflowName Name of workflow we want the collections of that are mapped to is
|
||||||
|
* @return List of collection handles mapped to the requested workflow
|
||||||
|
*/
|
||||||
|
public List<String> getCollectionHandlesMappedToWorklow(String workflowName);
|
||||||
}
|
}
|
||||||
|
@@ -7,22 +7,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.xmlworkflow.state;
|
package org.dspace.xmlworkflow.state;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.workflow.WorkflowException;
|
|
||||||
import org.dspace.xmlworkflow.Role;
|
import org.dspace.xmlworkflow.Role;
|
||||||
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
|
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
|
||||||
import org.dspace.xmlworkflow.state.actions.UserSelectionActionConfig;
|
import org.dspace.xmlworkflow.state.actions.UserSelectionActionConfig;
|
||||||
import org.dspace.xmlworkflow.state.actions.WorkflowActionConfig;
|
import org.dspace.xmlworkflow.state.actions.WorkflowActionConfig;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.service.InProgressUserService;
|
import org.dspace.xmlworkflow.storedcomponents.service.InProgressUserService;
|
||||||
|
import org.springframework.beans.factory.BeanNameAware;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Required;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that contains all the data of an xlworkflow step
|
* A class that contains all the data of an xlworkflow step
|
||||||
@@ -32,46 +32,36 @@ import org.dspace.xmlworkflow.storedcomponents.service.InProgressUserService;
|
|||||||
* @author Ben Bosman (ben at atmire dot com)
|
* @author Ben Bosman (ben at atmire dot com)
|
||||||
* @author Mark Diggory (markd at atmire dot com)
|
* @author Mark Diggory (markd at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public class Step {
|
public class Step implements BeanNameAware {
|
||||||
|
|
||||||
|
|
||||||
protected InProgressUserService inProgressUserService = XmlWorkflowServiceFactory.getInstance()
|
|
||||||
.getInProgressUserService();
|
|
||||||
protected XmlWorkflowFactory xmlWorkflowFactory = XmlWorkflowServiceFactory.getInstance().getWorkflowFactory();
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected InProgressUserService inProgressUserService;
|
||||||
|
|
||||||
private UserSelectionActionConfig userSelectionMethod;
|
private UserSelectionActionConfig userSelectionMethod;
|
||||||
private HashMap<String, WorkflowActionConfig> actionConfigsMap;
|
private List<WorkflowActionConfig> actions;
|
||||||
private List<String> actionConfigsList;
|
private Map<Integer, Step> outcomes = new HashMap<>();
|
||||||
private Map<Integer, String> outcomes;
|
|
||||||
private String id;
|
private String id;
|
||||||
private Role role;
|
private Role role;
|
||||||
private Workflow workflow;
|
private Workflow workflow;
|
||||||
private int requiredUsers;
|
private int requiredUsers = 1;
|
||||||
|
|
||||||
public Step(String id, Workflow workflow, Role role, UserSelectionActionConfig userSelectionMethod,
|
/**
|
||||||
List<String> actionConfigsList, Map<Integer, String> outcomes, int requiredUsers) {
|
* Get an WorkflowActionConfiguration object for the provided action identifier
|
||||||
this.actionConfigsMap = new HashMap<>();
|
* @param actionID the action id for which we want our action config
|
||||||
this.outcomes = outcomes;
|
* @return The corresponding WorkflowActionConfiguration
|
||||||
this.userSelectionMethod = userSelectionMethod;
|
* @throws WorkflowConfigurationException occurs if the provided action isn't part of the step
|
||||||
this.role = role;
|
*/
|
||||||
this.actionConfigsList = actionConfigsList;
|
public WorkflowActionConfig getActionConfig(String actionID) throws WorkflowConfigurationException {
|
||||||
this.id = id;
|
// First check the userSelectionMethod as this is not a regular "action"
|
||||||
userSelectionMethod.setStep(this);
|
if (userSelectionMethod != null && StringUtils.equals(userSelectionMethod.getId(), actionID)) {
|
||||||
this.requiredUsers = requiredUsers;
|
return userSelectionMethod;
|
||||||
this.workflow = workflow;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkflowActionConfig getActionConfig(String actionID) {
|
|
||||||
if (actionConfigsMap.get(actionID) != null) {
|
|
||||||
return actionConfigsMap.get(actionID);
|
|
||||||
} else {
|
|
||||||
WorkflowActionConfig action = xmlWorkflowFactory.createWorkflowActionConfig(actionID);
|
|
||||||
action.setStep(this);
|
|
||||||
actionConfigsMap.put(actionID, action);
|
|
||||||
return action;
|
|
||||||
}
|
}
|
||||||
|
for (WorkflowActionConfig actionConfig : actions) {
|
||||||
|
if (StringUtils.equals(actionConfig.getId(), actionID)) {
|
||||||
|
return actionConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new WorkflowConfigurationException("Action configuration not found for: " + actionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,8 +70,7 @@ public class Step {
|
|||||||
* @return a boolean
|
* @return a boolean
|
||||||
*/
|
*/
|
||||||
public boolean hasUI() {
|
public boolean hasUI() {
|
||||||
for (String actionConfigId : actionConfigsList) {
|
for (WorkflowActionConfig actionConfig : actions) {
|
||||||
WorkflowActionConfig actionConfig = getActionConfig(actionConfigId);
|
|
||||||
if (actionConfig.requiresUI()) {
|
if (actionConfig.requiresUI()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -89,8 +78,12 @@ public class Step {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNextStepID(int outcome)
|
/**
|
||||||
throws WorkflowException, IOException, WorkflowConfigurationException, SQLException {
|
* Get the next step based on out the outcome
|
||||||
|
* @param outcome the outcome of the previous step
|
||||||
|
* @return the next stepp or NULL if there is no step configured for this outcome
|
||||||
|
*/
|
||||||
|
public Step getNextStep(int outcome) {
|
||||||
return outcomes.get(outcome);
|
return outcomes.get(outcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,9 +102,9 @@ public class Step {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public WorkflowActionConfig getNextAction(WorkflowActionConfig currentAction) {
|
public WorkflowActionConfig getNextAction(WorkflowActionConfig currentAction) {
|
||||||
int index = actionConfigsList.indexOf(currentAction.getId());
|
int index = actions.indexOf(currentAction);
|
||||||
if (index < actionConfigsList.size() - 1) {
|
if (index < actions.size() - 1) {
|
||||||
return getActionConfig(actionConfigsList.get(index + 1));
|
return actions.get(index + 1);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -125,7 +118,6 @@ public class Step {
|
|||||||
return workflow;
|
return workflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if enough users have finished this step for it to continue
|
* Check if enough users have finished this step for it to continue
|
||||||
*
|
*
|
||||||
@@ -146,6 +138,78 @@ public class Step {
|
|||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public boolean skipStep() {
|
/**
|
||||||
// }
|
* Set the user selection configuration, this is required as every step requires one
|
||||||
|
* @param userSelectionMethod the user selection method configuration
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setUserSelectionMethod(UserSelectionActionConfig userSelectionMethod) {
|
||||||
|
this.userSelectionMethod = userSelectionMethod;
|
||||||
|
userSelectionMethod.setStep(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the outcomes as a map, if no outcomes are configured this step will be last step in the workflow
|
||||||
|
* @param outcomes the map containing the outcomes.
|
||||||
|
*/
|
||||||
|
public void setOutcomes(Map<Integer, Step> outcomes) {
|
||||||
|
this.outcomes = outcomes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the processing actions for the step. Processing actions contain the logic required to execute the required
|
||||||
|
* operations in each step.
|
||||||
|
* @return the actions configured for this step
|
||||||
|
*/
|
||||||
|
public List<WorkflowActionConfig> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the processing actions for the step. Processing actions contain the logic required to execute the required
|
||||||
|
* operations in each step.
|
||||||
|
* @param actions the list of actions
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setActions(List<WorkflowActionConfig> actions) {
|
||||||
|
for (WorkflowActionConfig workflowActionConfig : actions) {
|
||||||
|
workflowActionConfig.setStep(this);
|
||||||
|
}
|
||||||
|
this.actions = actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the workflow this step belongs to
|
||||||
|
* @param workflow the workflow configuration
|
||||||
|
*/
|
||||||
|
protected void setWorkflow(Workflow workflow) {
|
||||||
|
this.workflow = workflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the name of the bean in the identifier
|
||||||
|
* @param s the bean name
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setBeanName(String s) {
|
||||||
|
id = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the number of required users that need to execute this step before it is completed,
|
||||||
|
* the default is a single user
|
||||||
|
* @param requiredUsers the number of required users
|
||||||
|
*/
|
||||||
|
public void setRequiredUsers(int requiredUsers) {
|
||||||
|
this.requiredUsers = requiredUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the role of which users role should execute this step
|
||||||
|
* @param role the role to be configured for this step
|
||||||
|
*/
|
||||||
|
public void setRole(Role role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,18 +7,18 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.xmlworkflow.state;
|
package org.dspace.xmlworkflow.state;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.workflow.WorkflowException;
|
|
||||||
import org.dspace.xmlworkflow.Role;
|
import org.dspace.xmlworkflow.Role;
|
||||||
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
|
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
|
import org.springframework.beans.factory.BeanNameAware;
|
||||||
|
import org.springframework.beans.factory.annotation.Required;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that contains all the steps and roles involved in a certain
|
* Class that contains all the steps and roles involved in a certain
|
||||||
@@ -29,21 +29,11 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
|||||||
* @author Ben Bosman (ben at atmire dot com)
|
* @author Ben Bosman (ben at atmire dot com)
|
||||||
* @author Mark Diggory (markd at atmire dot com)
|
* @author Mark Diggory (markd at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public class Workflow {
|
public class Workflow implements BeanNameAware {
|
||||||
|
|
||||||
protected XmlWorkflowFactory xmlWorkflowFactory = XmlWorkflowServiceFactory.getInstance().getWorkflowFactory();
|
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private Step firstStep;
|
private Step firstStep;
|
||||||
private HashMap<String, Step> steps;
|
private List<Step> steps;
|
||||||
private LinkedHashMap<String, Role> roles;
|
|
||||||
|
|
||||||
|
|
||||||
public Workflow(String workflowID, LinkedHashMap<String, Role> roles) {
|
|
||||||
this.id = workflowID;
|
|
||||||
this.roles = roles;
|
|
||||||
this.steps = new HashMap<String, Step>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Step getFirstStep() {
|
public Step getFirstStep() {
|
||||||
return firstStep;
|
return firstStep;
|
||||||
@@ -56,46 +46,72 @@ public class Workflow {
|
|||||||
/*
|
/*
|
||||||
* Return a step with a given id
|
* Return a step with a given id
|
||||||
*/
|
*/
|
||||||
public Step getStep(String stepID) throws WorkflowConfigurationException, IOException {
|
public Step getStep(String stepID) throws WorkflowConfigurationException {
|
||||||
if (steps.get(id) != null) {
|
for (Step step : steps) {
|
||||||
return steps.get(id);
|
if (step.getId().equals(stepID)) {
|
||||||
} else {
|
return step;
|
||||||
Step step = xmlWorkflowFactory.createStep(this, stepID);
|
|
||||||
if (step == null) {
|
|
||||||
throw new WorkflowConfigurationException("Step definition not found for: " + stepID);
|
|
||||||
}
|
}
|
||||||
steps.put(stepID, step);
|
|
||||||
return step;
|
|
||||||
}
|
}
|
||||||
|
throw new WorkflowConfigurationException("Step definition not found for: " + stepID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Step getNextStep(Context context, XmlWorkflowItem wfi, Step currentStep, int outcome)
|
public Step getNextStep(Context context, XmlWorkflowItem wfi, Step currentStep, int outcome)
|
||||||
throws IOException, WorkflowConfigurationException, WorkflowException, SQLException {
|
throws WorkflowConfigurationException, SQLException {
|
||||||
String nextStepID = currentStep.getNextStepID(outcome);
|
Step nextStep = currentStep.getNextStep(outcome);
|
||||||
if (nextStepID != null) {
|
if (nextStep != null) {
|
||||||
Step nextStep = getStep(nextStepID);
|
|
||||||
if (nextStep == null) {
|
|
||||||
throw new WorkflowException(
|
|
||||||
"Error while processing outcome, the following action was undefined: " + nextStepID);
|
|
||||||
}
|
|
||||||
if (nextStep.isValidStep(context, wfi)) {
|
if (nextStep.isValidStep(context, wfi)) {
|
||||||
return nextStep;
|
return nextStep;
|
||||||
} else {
|
} else {
|
||||||
return getNextStep(context, wfi, nextStep, 0);
|
return getNextStep(context, wfi, nextStep, ActionResult.OUTCOME_COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//No next step, archive it
|
//No next step, archive it
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Required
|
||||||
public void setFirstStep(Step firstStep) {
|
public void setFirstStep(Step firstStep) {
|
||||||
|
firstStep.setWorkflow(this);
|
||||||
this.firstStep = firstStep;
|
this.firstStep = firstStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMap<String, Role> getRoles() {
|
/**
|
||||||
|
* Get the steps that need to be executed in this workflow before the item is archived
|
||||||
|
* @return the workflow steps
|
||||||
|
*/
|
||||||
|
public List<Step> getSteps() {
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the steps that need to be executed in this workflow before the item is archived
|
||||||
|
* @param steps the workflow steps
|
||||||
|
*/
|
||||||
|
@Required
|
||||||
|
public void setSteps(List<Step> steps) {
|
||||||
|
for (Step step : steps) {
|
||||||
|
step.setWorkflow(this);
|
||||||
|
}
|
||||||
|
this.steps = steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the roles that are used in this workflow
|
||||||
|
* @return a map containing the roles, the role name will the key, the role itself the value
|
||||||
|
*/
|
||||||
|
public Map<String, Role> getRoles() {
|
||||||
|
Map<String, Role> roles = new HashMap<>();
|
||||||
|
for (Step step : steps) {
|
||||||
|
if (step.getRole() != null) {
|
||||||
|
roles.put(step.getRole().getName(), step.getRole());
|
||||||
|
}
|
||||||
|
}
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBeanName(String s) {
|
||||||
|
id = s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,17 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
---------------------------------------------------------------
|
||||||
|
-- DS-4239 Migrate the workflow.xml to spring
|
||||||
|
---------------------------------------------------------------
|
||||||
|
-- This script will rename the default workflow "default" name
|
||||||
|
-- to the new "defaultWorkflow" identifier
|
||||||
|
---------------------------------------------------------------
|
||||||
|
|
||||||
|
UPDATE cwf_pooltask SET workflow_id='defaultWorkflow' WHERE workflow_id='default';
|
||||||
|
UPDATE cwf_claimtask SET workflow_id='defaultWorkflow' WHERE workflow_id='default';
|
@@ -0,0 +1,17 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
---------------------------------------------------------------
|
||||||
|
-- DS-4239 Migrate the workflow.xml to spring
|
||||||
|
---------------------------------------------------------------
|
||||||
|
-- This script will rename the default workflow "default" name
|
||||||
|
-- to the new "defaultWorkflow" identifier
|
||||||
|
---------------------------------------------------------------
|
||||||
|
|
||||||
|
UPDATE cwf_pooltask SET workflow_id='defaultWorkflow' WHERE workflow_id='default';
|
||||||
|
UPDATE cwf_claimtask SET workflow_id='defaultWorkflow' WHERE workflow_id='default';
|
@@ -0,0 +1,17 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
---------------------------------------------------------------
|
||||||
|
-- DS-4239 Migrate the workflow.xml to spring
|
||||||
|
---------------------------------------------------------------
|
||||||
|
-- This script will rename the default workflow "default" name
|
||||||
|
-- to the new "defaultWorkflow" identifier
|
||||||
|
---------------------------------------------------------------
|
||||||
|
|
||||||
|
UPDATE cwf_pooltask SET workflow_id='defaultWorkflow' WHERE workflow_id='default';
|
||||||
|
UPDATE cwf_claimtask SET workflow_id='defaultWorkflow' WHERE workflow_id='default';
|
@@ -22,7 +22,6 @@ import org.dspace.content.Collection;
|
|||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.handle.factory.HandleServiceFactory;
|
import org.dspace.handle.factory.HandleServiceFactory;
|
||||||
import org.dspace.handle.service.HandleService;
|
import org.dspace.handle.service.HandleService;
|
||||||
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
|
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -64,25 +63,20 @@ public class WorkflowDefinitionController {
|
|||||||
@GetMapping("{workflowName}/collections")
|
@GetMapping("{workflowName}/collections")
|
||||||
public List<CollectionRest> get(HttpServletRequest request, HttpServletResponse response,
|
public List<CollectionRest> get(HttpServletRequest request, HttpServletResponse response,
|
||||||
@PathVariable String workflowName) throws SQLException {
|
@PathVariable String workflowName) throws SQLException {
|
||||||
try {
|
if (xmlWorkflowFactory.workflowByThisNameExists(workflowName)) {
|
||||||
if (xmlWorkflowFactory.workflowByThisNameExists(workflowName)) {
|
List<String> collectionsHandlesMappedToWorkflow
|
||||||
List<String> collectionsHandlesMappedToWorkflow
|
= xmlWorkflowFactory.getCollectionHandlesMappedToWorklow(workflowName);
|
||||||
= xmlWorkflowFactory.getCollectionHandlesMappedToWorklow(workflowName);
|
List<CollectionRest> collectionResourcesFromHandles = new ArrayList<>();
|
||||||
List<CollectionRest> collectionResourcesFromHandles = new ArrayList<>();
|
for (String handle : collectionsHandlesMappedToWorkflow) {
|
||||||
for (String handle : collectionsHandlesMappedToWorkflow) {
|
Context context = ContextUtil.obtainContext(request);
|
||||||
Context context = ContextUtil.obtainContext(request);
|
Collection collection = (Collection) handleService.resolveToObject(context, handle);
|
||||||
Collection collection = (Collection) handleService.resolveToObject(context, handle);
|
if (collection != null) {
|
||||||
if (collection != null) {
|
collectionResourcesFromHandles.add(converter.toRest(collection, utils.obtainProjection()));
|
||||||
collectionResourcesFromHandles.add(converter.toRest(collection, utils.obtainProjection()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return collectionResourcesFromHandles;
|
|
||||||
} else {
|
|
||||||
throw new ResourceNotFoundException("No workflow with name " + workflowName + " is configured");
|
|
||||||
}
|
}
|
||||||
} catch (WorkflowConfigurationException e) {
|
return collectionResourcesFromHandles;
|
||||||
// TODO ? Better exception?
|
} else {
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
throw new ResourceNotFoundException("No workflow with name " + workflowName + " is configured");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -42,27 +42,21 @@ public class WorkflowDefinitionRestRepository extends DSpaceRestRepository<Workf
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorkflowDefinitionRest findOne(Context context, String workflowName) {
|
public WorkflowDefinitionRest findOne(Context context, String workflowName) {
|
||||||
try {
|
if (xmlWorkflowFactory.workflowByThisNameExists(workflowName)) {
|
||||||
if (xmlWorkflowFactory.workflowByThisNameExists(workflowName)) {
|
try {
|
||||||
return converter.toRest(xmlWorkflowFactory.getWorkflowByName(workflowName), utils.obtainProjection());
|
return converter.toRest(xmlWorkflowFactory.getWorkflowByName(workflowName), utils.obtainProjection());
|
||||||
} else {
|
} catch (WorkflowConfigurationException e) {
|
||||||
throw new ResourceNotFoundException("No workflow with name " + workflowName + " is configured");
|
throw new ResourceNotFoundException("No workflow with name " + workflowName + " is configured");
|
||||||
}
|
}
|
||||||
} catch (WorkflowConfigurationException e) {
|
} else {
|
||||||
// TODO ? Better exception?
|
throw new ResourceNotFoundException("No workflow with name " + workflowName + " is configured");
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<WorkflowDefinitionRest> findAll(Context context, Pageable pageable) {
|
public Page<WorkflowDefinitionRest> findAll(Context context, Pageable pageable) {
|
||||||
try {
|
List<Workflow> workflows = xmlWorkflowFactory.getAllConfiguredWorkflows();
|
||||||
List<Workflow> workflows = xmlWorkflowFactory.getAllConfiguredWorkflows();
|
return converter.toRestPage(workflows, pageable, workflows.size(), utils.obtainProjection());
|
||||||
return converter.toRestPage(workflows, pageable, workflows.size(), utils.obtainProjection());
|
|
||||||
} catch (WorkflowConfigurationException e) {
|
|
||||||
// TODO ? Better exception?
|
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* GET endpoint that returns the workflow definition that applies to a specific collection eventually fallback
|
* GET endpoint that returns the workflow definition that applies to a specific collection eventually fallback
|
||||||
@@ -73,17 +67,17 @@ public class WorkflowDefinitionRestRepository extends DSpaceRestRepository<Workf
|
|||||||
*/
|
*/
|
||||||
@SearchRestMethod(name = "findByCollection")
|
@SearchRestMethod(name = "findByCollection")
|
||||||
public WorkflowDefinitionRest findByCollection(@Parameter(value = "uuid") UUID collectionId) throws SQLException {
|
public WorkflowDefinitionRest findByCollection(@Parameter(value = "uuid") UUID collectionId) throws SQLException {
|
||||||
try {
|
Context context = obtainContext();
|
||||||
Context context = obtainContext();
|
Collection collectionFromUuid = collectionService.find(context, collectionId);
|
||||||
Collection collectionFromUuid = collectionService.find(context, collectionId);
|
if (collectionFromUuid != null) {
|
||||||
if (collectionFromUuid != null) {
|
try {
|
||||||
return converter.toRest(xmlWorkflowFactory.getWorkflow(collectionFromUuid), utils.obtainProjection());
|
return converter.toRest(xmlWorkflowFactory.getWorkflow(collectionFromUuid), utils.obtainProjection());
|
||||||
} else {
|
} catch (WorkflowConfigurationException e) {
|
||||||
throw new ResourceNotFoundException("Collection with id " + collectionId + " not found");
|
throw new ResourceNotFoundException("No workflow for this collection fault and " +
|
||||||
|
"no defaultWorkflow found");
|
||||||
}
|
}
|
||||||
} catch (WorkflowConfigurationException e) {
|
} else {
|
||||||
// TODO ? Better exception?
|
throw new ResourceNotFoundException("Collection with id " + collectionId + " not found");
|
||||||
throw new RuntimeException(e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||||
import org.dspace.app.rest.model.WorkflowDefinitionRest;
|
import org.dspace.app.rest.model.WorkflowDefinitionRest;
|
||||||
@@ -84,16 +85,18 @@ public class WorkflowDefinitionRestRepositoryIT extends AbstractControllerIntegr
|
|||||||
firstNonDefaultWorkflowName = workflow.getID();
|
firstNonDefaultWorkflowName = workflow.getID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//When we call this facets endpoint
|
if (StringUtils.isNotBlank(firstNonDefaultWorkflowName)) {
|
||||||
getClient().perform(get(WORKFLOW_DEFINITIONS_ENDPOINT + "/" + firstNonDefaultWorkflowName))
|
//When we call this facets endpoint
|
||||||
//We expect a 200 OK status
|
getClient().perform(get(WORKFLOW_DEFINITIONS_ENDPOINT + "/" + firstNonDefaultWorkflowName))
|
||||||
.andExpect(status().isOk())
|
//We expect a 200 OK status
|
||||||
//There needs to be a self link to this endpoint
|
.andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.self.href", containsString(WORKFLOW_DEFINITIONS_ENDPOINT)))
|
//There needs to be a self link to this endpoint
|
||||||
// its name is name of non-default workflow
|
.andExpect(jsonPath("$._links.self.href", containsString(WORKFLOW_DEFINITIONS_ENDPOINT)))
|
||||||
.andExpect(jsonPath("$.name", equalToIgnoringCase(firstNonDefaultWorkflowName)))
|
// its name is name of non-default workflow
|
||||||
// is not default
|
.andExpect(jsonPath("$.name", equalToIgnoringCase(firstNonDefaultWorkflowName)))
|
||||||
.andExpect(jsonPath("$.isDefault", is(false)));
|
// is not default
|
||||||
|
.andExpect(jsonPath("$.isDefault", is(false)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -190,25 +193,26 @@ public class WorkflowDefinitionRestRepositoryIT extends AbstractControllerIntegr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> handlesOfMappedCollections
|
if (StringUtils.isNotBlank(firstNonDefaultWorkflowName)) {
|
||||||
= xmlWorkflowFactory.getCollectionHandlesMappedToWorklow(firstNonDefaultWorkflowName);
|
List<String> handlesOfMappedCollections
|
||||||
|
= xmlWorkflowFactory.getCollectionHandlesMappedToWorklow(firstNonDefaultWorkflowName);
|
||||||
//When we call this facets endpoint
|
//When we call this facets endpoint
|
||||||
if (handlesOfMappedCollections.size() > 0) {
|
if (handlesOfMappedCollections.size() > 0) {
|
||||||
//returns array of collection jsons that are mapped to given workflow
|
//returns array of collection jsons that are mapped to given workflow
|
||||||
MvcResult result = getClient().perform(get(WORKFLOW_DEFINITIONS_ENDPOINT + "/"
|
MvcResult result = getClient().perform(get(WORKFLOW_DEFINITIONS_ENDPOINT + "/"
|
||||||
+ firstNonDefaultWorkflowName + "/collections")).andReturn();
|
+ firstNonDefaultWorkflowName + "/collections")).andReturn();
|
||||||
String response = result.getResponse().getContentAsString();
|
String response = result.getResponse().getContentAsString();
|
||||||
JSONArray collectionsResult = new JSONArray(response);
|
JSONArray collectionsResult = new JSONArray(response);
|
||||||
assertEquals(collectionsResult.length(), handlesOfMappedCollections.size());
|
assertEquals(collectionsResult.length(), handlesOfMappedCollections.size());
|
||||||
} else {
|
} else {
|
||||||
//no collections mapped to this workflow
|
//no collections mapped to this workflow
|
||||||
getClient().perform(get(WORKFLOW_DEFINITIONS_ENDPOINT + "/"
|
getClient().perform(get(WORKFLOW_DEFINITIONS_ENDPOINT + "/"
|
||||||
+ firstNonDefaultWorkflowName + "/collections"))
|
+ firstNonDefaultWorkflowName + "/collections"))
|
||||||
//We expect a 200 OK status
|
//We expect a 200 OK status
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
//results in empty list
|
//results in empty list
|
||||||
.andExpect(jsonPath("$", empty()));
|
.andExpect(jsonPath("$", empty()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -115,7 +115,6 @@
|
|||||||
<bean class="org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItemServiceImpl"/>
|
<bean class="org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItemServiceImpl"/>
|
||||||
<bean class="org.dspace.xmlworkflow.XmlWorkflowServiceImpl"/>
|
<bean class="org.dspace.xmlworkflow.XmlWorkflowServiceImpl"/>
|
||||||
<bean class="org.dspace.xmlworkflow.WorkflowRequirementsServiceImpl"/>
|
<bean class="org.dspace.xmlworkflow.WorkflowRequirementsServiceImpl"/>
|
||||||
<bean class="org.dspace.xmlworkflow.XmlWorkflowFactoryImpl"/>
|
|
||||||
|
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
185
dspace/config/spring/api/workflow.xml
Normal file
185
dspace/config/spring/api/workflow.xml
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
|
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||||
|
|
||||||
|
<bean class="org.dspace.xmlworkflow.XmlWorkflowFactoryImpl">
|
||||||
|
<property name="workflowMapping">
|
||||||
|
<util:map>
|
||||||
|
<entry key="defaultWorkflow"
|
||||||
|
value-ref="defaultWorkflow"/>
|
||||||
|
<!-- <entry key="123456789/4" value-ref="selectSingleReviewer"/>-->
|
||||||
|
<!-- <entry key="123456789/5" value-ref="scoreReview"/>-->
|
||||||
|
</util:map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!--Standard DSpace workflow-->
|
||||||
|
<bean name="defaultWorkflow" class="org.dspace.xmlworkflow.state.Workflow">
|
||||||
|
<property name="firstStep" ref="reviewstep"/>
|
||||||
|
<property name="steps">
|
||||||
|
<util:list>
|
||||||
|
<ref bean="reviewstep"/>
|
||||||
|
<ref bean="editstep"/>
|
||||||
|
<ref bean="finaleditstep"/>
|
||||||
|
</util:list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="reviewstep" class="org.dspace.xmlworkflow.state.Step">
|
||||||
|
<property name="userSelectionMethod" ref="claimaction"/>
|
||||||
|
<property name="role">
|
||||||
|
<bean name="reviewer" class="org.dspace.xmlworkflow.Role">
|
||||||
|
<property name="scope" value="#{ T(org.dspace.xmlworkflow.Role.Scope).COLLECTION}"/>
|
||||||
|
<property name="name" value="Reviewer"/>
|
||||||
|
<property name="description"
|
||||||
|
value="The people responsible for this step are able to edit the metadata of incoming submissions, and then accept or reject them."/>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
<property name="outcomes">
|
||||||
|
<util:map>
|
||||||
|
<entry key="#{ T(org.dspace.xmlworkflow.state.actions.ActionResult).OUTCOME_COMPLETE}"
|
||||||
|
value-ref="editstep"/>
|
||||||
|
</util:map>
|
||||||
|
</property>
|
||||||
|
<property name="actions">
|
||||||
|
<util:list>
|
||||||
|
<ref bean="reviewaction"/>
|
||||||
|
</util:list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
<bean name="editstep" class="org.dspace.xmlworkflow.state.Step">
|
||||||
|
<property name="userSelectionMethod" ref="claimaction"/>
|
||||||
|
<property name="role">
|
||||||
|
<bean name="editor" class="org.dspace.xmlworkflow.Role">
|
||||||
|
<property name="scope" value="#{ T(org.dspace.xmlworkflow.Role.Scope).COLLECTION}"/>
|
||||||
|
<property name="name" value="Editor"/>
|
||||||
|
<property name="description"
|
||||||
|
value="The people responsible for this step are able to edit the metadata of incoming submissions, and then accept or reject them."/>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
<property name="outcomes">
|
||||||
|
<util:map>
|
||||||
|
<entry key="#{ T(org.dspace.xmlworkflow.state.actions.ActionResult).OUTCOME_COMPLETE}"
|
||||||
|
value-ref="finaleditstep"/>
|
||||||
|
</util:map>
|
||||||
|
</property>
|
||||||
|
<property name="actions">
|
||||||
|
<list>
|
||||||
|
<ref bean="editaction"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
<bean name="finaleditstep" class="org.dspace.xmlworkflow.state.Step">
|
||||||
|
<property name="userSelectionMethod" ref="claimaction"/>
|
||||||
|
<property name="role">
|
||||||
|
<bean name="finaleditor" class="org.dspace.xmlworkflow.Role">
|
||||||
|
<property name="scope" value="#{ T(org.dspace.xmlworkflow.Role.Scope).COLLECTION}"/>
|
||||||
|
<property name="name" value="Final Editor"/>
|
||||||
|
<property name="description"
|
||||||
|
value="The people responsible for this step are able to edit the metadata of incoming submissions, but will not be able to reject them."/>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
<property name="actions">
|
||||||
|
<list>
|
||||||
|
<ref bean="finaleditaction"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
<!--Workflow where a reviewManager can select a single review who will then either accept/reject the item-->
|
||||||
|
<bean name="selectSingleReviewer" class="org.dspace.xmlworkflow.state.Workflow">
|
||||||
|
<property name="firstStep" ref="selectReviewerStep"/>
|
||||||
|
<property name="steps">
|
||||||
|
<util:list>
|
||||||
|
<ref bean="selectReviewerStep"/>
|
||||||
|
<ref bean="singleUserReviewStep"/>
|
||||||
|
</util:list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="selectReviewerStep" class="org.dspace.xmlworkflow.state.Step">
|
||||||
|
<property name="userSelectionMethod" ref="claimaction"/>
|
||||||
|
<property name="role">
|
||||||
|
<bean name="reviewmanagers" class="org.dspace.xmlworkflow.Role">
|
||||||
|
<property name="scope" value="#{ T(org.dspace.xmlworkflow.Role.Scope).REPOSITORY}"/>
|
||||||
|
<property name="name" value="ReviewManagers"/>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
<property name="actions">
|
||||||
|
<list>
|
||||||
|
<ref bean="selectrevieweraction" />
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="outcomes">
|
||||||
|
<util:map>
|
||||||
|
<entry key="#{ T(org.dspace.xmlworkflow.state.actions.ActionResult).OUTCOME_COMPLETE}"
|
||||||
|
value-ref="singleUserReviewStep"/>
|
||||||
|
</util:map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="singleUserReviewStep" class="org.dspace.xmlworkflow.state.Step">
|
||||||
|
<property name="userSelectionMethod" ref="autoassignAction"/>
|
||||||
|
<property name="role">
|
||||||
|
<bean name="reviewer" class="org.dspace.xmlworkflow.Role">
|
||||||
|
<property name="scope" value="#{ T(org.dspace.xmlworkflow.Role.Scope).ITEM}"/>
|
||||||
|
<property name="name" value="Reviewer"/>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
<property name="actions">
|
||||||
|
<list>
|
||||||
|
<ref bean="singleuserreviewaction" />
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="outcomes">
|
||||||
|
<util:map>
|
||||||
|
<entry key="#{ T(org.dspace.xmlworkflow.state.actions.processingaction.SingleUserReviewAction).OUTCOME_REJECT}" value-ref="selectReviewerStep"/>
|
||||||
|
</util:map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!--Workflow where a number of users will perform reviews on an item and depending on the scores the item will be archived/rejected-->
|
||||||
|
<bean name="scoreReview" class="org.dspace.xmlworkflow.state.Workflow">
|
||||||
|
<property name="firstStep" ref="scoreReviewStep"/>
|
||||||
|
<property name="steps">
|
||||||
|
<util:list>
|
||||||
|
<ref bean="scoreReviewStep"/>
|
||||||
|
<ref bean="evaluationStep"/>
|
||||||
|
</util:list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="scoreReviewStep" class="org.dspace.xmlworkflow.state.Step">
|
||||||
|
<property name="userSelectionMethod" ref="claimaction"/>
|
||||||
|
<property name="role">
|
||||||
|
<bean name="scoreReviewers" class="org.dspace.xmlworkflow.Role">
|
||||||
|
<property name="scope" value="#{ T(org.dspace.xmlworkflow.Role.Scope).COLLECTION}"/>
|
||||||
|
<property name="name" value="ScoreReviewers"/>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
<property name="outcomes">
|
||||||
|
<util:map>
|
||||||
|
<entry key="#{ T(org.dspace.xmlworkflow.state.actions.ActionResult).OUTCOME_COMPLETE}"
|
||||||
|
value-ref="evaluationStep"/>
|
||||||
|
</util:map>
|
||||||
|
</property>
|
||||||
|
<property name="actions">
|
||||||
|
<list>
|
||||||
|
<ref bean="scorereviewaction"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="requiredUsers" value="2"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="evaluationStep" class="org.dspace.xmlworkflow.state.Step">
|
||||||
|
<property name="userSelectionMethod" ref="noUserSelectionAction"/>
|
||||||
|
<property name="actions">
|
||||||
|
<list>
|
||||||
|
<ref bean="evaluationaction"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</beans>
|
@@ -1,89 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<wf-config>
|
|
||||||
<workflow-map>
|
|
||||||
<name-map collection="default" workflow="default"/>
|
|
||||||
<!--<name-map collection="123456789/4" workflow="selectSingleReviewer"/>-->
|
|
||||||
<!--<name-map collection="123456789/5" workflow="scoreReview"/>-->
|
|
||||||
</workflow-map>
|
|
||||||
|
|
||||||
<!--Standard workflow step-->
|
|
||||||
<workflow start="reviewstep" id="default">
|
|
||||||
|
|
||||||
<roles>
|
|
||||||
<role id="reviewer" name="Reviewer" description="The people responsible for this step are able to edit the metadata of incoming submissions, and then accept or reject them." />
|
|
||||||
<role id="editor" name="Editor" description="The people responsible for this step are able to edit the metadata of incoming submissions, and then accept or reject them."/>
|
|
||||||
<role id="finaleditor" name="Final Editor" description="The people responsible for this step are able to edit the metadata of incoming submissions, but will not be able to reject them."/>
|
|
||||||
</roles>
|
|
||||||
|
|
||||||
<step id="reviewstep" role="reviewer" userSelectionMethod="claimaction">
|
|
||||||
<outcomes>
|
|
||||||
<step status="0">editstep</step>
|
|
||||||
</outcomes>
|
|
||||||
<actions>
|
|
||||||
<action id="reviewaction"/>
|
|
||||||
</actions>
|
|
||||||
</step>
|
|
||||||
<step id="editstep" role="editor" userSelectionMethod="claimaction">
|
|
||||||
<outcomes>
|
|
||||||
<step status="0">finaleditstep</step>
|
|
||||||
</outcomes>
|
|
||||||
<actions>
|
|
||||||
<action id="editaction"/>
|
|
||||||
</actions>
|
|
||||||
</step>
|
|
||||||
<step id="finaleditstep" role="finaleditor" userSelectionMethod="claimaction">
|
|
||||||
<actions>
|
|
||||||
<action id="finaleditaction"/>
|
|
||||||
</actions>
|
|
||||||
</step>
|
|
||||||
</workflow>
|
|
||||||
|
|
||||||
<!--Workflow where a reviewManager can select a single review who will then either accept/reject the item-->
|
|
||||||
<workflow id="selectSingleReviewer" start="selectReviewerStep">
|
|
||||||
<roles>
|
|
||||||
<role id="reviewer" name="Reviewer" scope="item" />
|
|
||||||
<role id="reviewmanagers" name="ReviewManagers" scope="repository"/>
|
|
||||||
</roles>
|
|
||||||
|
|
||||||
|
|
||||||
<step id="selectReviewerStep" role="reviewmanagers" userSelectionMethod="claimaction">
|
|
||||||
<outcomes>
|
|
||||||
<step status="0">singleUserReviewStep</step>
|
|
||||||
</outcomes>
|
|
||||||
<actions>
|
|
||||||
<action id="selectrevieweraction"/>
|
|
||||||
</actions>
|
|
||||||
</step>
|
|
||||||
|
|
||||||
<step id="singleUserReviewStep" role="reviewer" userSelectionMethod="autoassignAction">
|
|
||||||
<outcomes>
|
|
||||||
<step status="1">selectReviewerStep</step>
|
|
||||||
</outcomes>
|
|
||||||
<actions>
|
|
||||||
<action id="singleuserreviewaction"/>
|
|
||||||
</actions>
|
|
||||||
</step>
|
|
||||||
|
|
||||||
</workflow>
|
|
||||||
|
|
||||||
<!--Workflow where a number of users will perform reviews on an item and depending on the scores the item will be archived/rejected-->
|
|
||||||
<workflow id="scoreReview" start="scoreReviewStep">
|
|
||||||
<roles>
|
|
||||||
<role id="scoreReviewers" name="ScoreReviewers" scope="collection" description="The people responsible to select a single reviewer for the submission"/>
|
|
||||||
</roles>
|
|
||||||
|
|
||||||
<step id="scoreReviewStep" role="scoreReviewers" userSelectionMethod="claimaction" requiredUsers="2">
|
|
||||||
<outcomes>
|
|
||||||
<step status="0">evaluationStep</step>
|
|
||||||
</outcomes>
|
|
||||||
<actions>
|
|
||||||
<action id="scorereviewaction"/>
|
|
||||||
</actions>
|
|
||||||
</step>
|
|
||||||
<step id="evaluationStep" userSelectionMethod="noUserSelectionAction">
|
|
||||||
<actions>
|
|
||||||
<action id="evaluationaction"/>
|
|
||||||
</actions>
|
|
||||||
</step>
|
|
||||||
</workflow>
|
|
||||||
</wf-config>
|
|
Reference in New Issue
Block a user