Merge pull request #75 from atmire/dspace3-workflow

[DS-1249] Configurable Workflow Improvements
This commit is contained in:
Hardy Pottinger
2012-09-19 13:46:34 -07:00
12 changed files with 130 additions and 37 deletions

View File

@@ -310,7 +310,8 @@ public class DescribeStep extends AbstractProcessingStep
DCValue[] values = item.getMetadata(inputs[i].getSchema(),
inputs[i].getElement(), inputs[i].getQualifier(), Item.ANY);
if (inputs[i].isRequired() && values.length == 0)
if ((inputs[i].isRequired() && values.length == 0) &&
inputs[i].isVisible(subInfo.isInWorkflow() ? DCInput.WORKFLOW_SCOPE : DCInput.SUBMISSION_SCOPE))
{
// since this field is missing add to list of error fields
addErrorField(request, getFieldName(inputs[i]));

View File

@@ -15,12 +15,10 @@ import org.dspace.core.ConfigurationManager;
import org.dspace.core.Email;
import org.dspace.core.I18nUtil;
import org.apache.log4j.Logger;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.xmlworkflow.state.Workflow;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.sql.SQLException;
@@ -211,10 +209,14 @@ public class WorkflowUtils extends Util{
/*
* Deletes a role group linked to a given role and a collection
*/
public static void deleteRoleGroup(Context context, int collectionID, String roleID) throws SQLException {
CollectionRole ass = CollectionRole.find(context,collectionID,roleID);
public static void deleteRoleGroup(Context context, Collection collection, String roleID) throws SQLException, IOException, WorkflowConfigurationException {
Workflow workflow = WorkflowFactory.getWorkflow(collection);
Role role = workflow.getRoles().get(roleID);
if(role.getScope() == Role.Scope.COLLECTION){
CollectionRole ass = CollectionRole.find(context, collection.getID(), roleID);
ass.delete();
}
}
public static HashMap<String, Role> getCollectionRoles(Collection thisCollection) throws IOException, WorkflowConfigurationException {
@@ -236,6 +238,46 @@ public class WorkflowUtils extends Util{
return result;
}
public static HashMap<String, Role> getCollectionAndRepositoryRoles(Collection thisCollection) throws IOException, WorkflowConfigurationException {
Workflow workflow = WorkflowFactory.getWorkflow(thisCollection);
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
if(workflow != null){
//Make sure we find one
HashMap<String, Role> allRoles = workflow.getRoles();
//We have retrieved all our roles, not get the ones which can be configured by the collection
for(String roleId : allRoles.keySet()){
Role role = allRoles.get(roleId);
// We just require the roles which have a scope of collection
if((role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY) && !role.isInternal()){
result.put(roleId, role);
}
}
}
return result;
}
public static HashMap<String, Role> getAllExternalRoles(Collection thisCollection) throws IOException, WorkflowConfigurationException {
Workflow workflow = WorkflowFactory.getWorkflow(thisCollection);
LinkedHashMap<String, Role> result = new LinkedHashMap<String, Role>();
if(workflow != null){
//Make sure we find one
HashMap<String, Role> allRoles = workflow.getRoles();
//We have retrieved all our roles, not get the ones which can be configured by the collection
for(String roleId : allRoles.keySet()){
Role role = allRoles.get(roleId);
// We just require the roles which have a scope of collection
if(!role.isInternal()){
result.put(roleId, role);
}
}
}
return result;
}
public static Group getRoleGroup(Context context, int collectionId, Role role) throws SQLException {
if(role.getScope() == Role.Scope.REPOSITORY){
return Group.findByName(context, role.getName());

View File

@@ -31,6 +31,7 @@
<%@ page import="org.dspace.content.Bitstream" %>
<%@ page import="org.dspace.content.BitstreamFormat" %>
<%@ page import="org.dspace.content.Bundle" %>
<%@ page import="org.dspace.core.ConfigurationManager" %>
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
@@ -46,6 +47,7 @@
boolean showChecksums = ((Boolean) request.getAttribute("show.checksums")).booleanValue();
request.setAttribute("LanguageSwitch", "hide");
boolean allowFileEditing = !subInfo.isInWorkflow() || ConfigurationManager.getBooleanProperty("workflow", "reviewer.file-edit");
%>
<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.upload-file-list.title">
@@ -90,7 +92,7 @@
}
// Don't display last column ("Remove") in workflow mode
if (!subInfo.isInWorkflow())
if (allowFileEditing)
{
// Whether it's an odd or even column depends on whether we're showing checksums
String column = (showChecksums ? "Even" : "Odd");
@@ -163,7 +165,7 @@
}
// Don't display "remove" button in workflow mode
if (!subInfo.isInWorkflow())
if (allowFileEditing)
{
// Whether it's an odd or even column depends on whether we're showing checksums
String column = (showChecksums ? "Even" : "Odd");
@@ -188,7 +190,7 @@
<%-- Show information about how to verify correct upload, but not in workflow
mode! --%>
<%
if (!subInfo.isInWorkflow())
if (allowFileEditing)
{
%>
<p class="uploadHelp"><fmt:message key="jsp.submit.upload-file-list.info3"/></p>
@@ -223,7 +225,7 @@
<center>
<%
// Don't allow files to be added in workflow mode
if (!subInfo.isInWorkflow())
if (allowFileEditing)
{
%>
<p><input type="submit" name="submit_more" value="<fmt:message key="jsp.submit.upload-file-list.button4"/>" /></p>

View File

@@ -488,18 +488,24 @@ public class FlowContainerUtils
}
private static Group getXMLWorkflowRole(Context context, int collectionID, String roleName, Collection collection, Group roleGroup) throws IOException, WorkflowConfigurationException, SQLException, AuthorizeException {
Role role = WorkflowUtils.getCollectionRoles(collection).get(roleName);
if(role.getScope() == Role.Scope.COLLECTION){
Role role = WorkflowUtils.getCollectionAndRepositoryRoles(collection).get(roleName);
if(role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY){
roleGroup = WorkflowUtils.getRoleGroup(context, collectionID, role);
if(roleGroup == null){
AuthorizeManager.authorizeAction(context, collection, Constants.WRITE);
roleGroup = Group.create(context);
if(role.getScope() == Role.Scope.COLLECTION){
roleGroup.setName("COLLECTION_" + collection.getID() + "_WORKFLOW_ROLE_" + roleName);
}else{
roleGroup.setName(role.getName());
}
roleGroup.update();
AuthorizeManager.addPolicy(context, collection, Constants.ADD, roleGroup);
if(role.getScope() == Role.Scope.COLLECTION){
WorkflowUtils.createCollectionWorkflowRole(context, collectionID, roleName, roleGroup);
}
}
}
return roleGroup;
}
@@ -513,7 +519,7 @@ public class FlowContainerUtils
* @param groupID The id of the group associated with this role.
* @return A process result's object.
*/
public static FlowResult processDeleteCollectionRole(Context context, int collectionID, String roleName, int groupID) throws SQLException, UIException, IOException, AuthorizeException
public static FlowResult processDeleteCollectionRole(Context context, int collectionID, String roleName, int groupID) throws SQLException, UIException, IOException, AuthorizeException, WorkflowConfigurationException
{
FlowResult result = new FlowResult();
@@ -530,7 +536,7 @@ public class FlowContainerUtils
collection.removeSubmitters();
}
else{
WorkflowUtils.deleteRoleGroup(context, collectionID, roleName);
WorkflowUtils.deleteRoleGroup(context, collection, roleName);
}
// else if (ROLE_WF_STEP1.equals(roleName))
// {

View File

@@ -90,6 +90,7 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer
private static final Message T_label_default_read = message("xmlui.administrative.collection.AssignCollectionRoles.label_default_read");
private static final Message T_sysadmins_only = message("xmlui.administrative.collection.AssignCollectionRoles.sysadmins_only");
private static final Message T_sysadmins_only_repository_role = message("xmlui.administrative.collection.AssignCollectionRoles.repository_role");
private static final Message T_not_allowed = message("xmlui.administrative.collection.AssignCollectionRoles.not_allowed");
@@ -116,7 +117,7 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer
HashMap<String, Role> roles = null;
try {
roles = WorkflowUtils.getCollectionRoles(thisCollection);
roles = WorkflowUtils.getAllExternalRoles(thisCollection);
} catch (WorkflowConfigurationException e) {
log.error(LogManager.getHeader(context, "error while getting collection roles", "Collection id: " + thisCollection.getID()));
} catch (IOException e) {
@@ -361,16 +362,35 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer
for(String roleId: roles.keySet()){
Role role = roles.get(roleId);
if (role.getScope() == Role.Scope.COLLECTION) {
if (role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY) {
tableRow = rolesTable.addRow(Row.ROLE_DATA);
tableRow.addCell(Cell.ROLE_HEADER).addContent(role.getName());
Group roleGroup = WorkflowUtils.getRoleGroup(context, thisCollection.getID(), role);
if (roleGroup != null) {
if(role.getScope() == Role.Scope.REPOSITORY){
if(AuthorizeManager.isAdmin(context)){
tableRow.addCell().addXref(baseURL + "&submit_edit_wf_role_" + roleId, roleGroup.getName());
}else{
Cell cell = tableRow.addCell();
cell.addContent(roleGroup.getName());
cell.addHighlight("fade").addContent(T_sysadmins_only_repository_role);
}
}else{
tableRow.addCell().addXref(baseURL + "&submit_edit_wf_role_" + roleId, roleGroup.getName());
}
if (role.getScope() == Role.Scope.COLLECTION) {
addAdministratorOnlyButton(tableRow.addCell(), "submit_delete_wf_role_" + roleId, T_delete);
} else {
tableRow.addCell();
}
} else {
tableRow.addCell().addContent(T_no_role);
if (role.getScope() == Role.Scope.COLLECTION || role.getScope() == Role.Scope.REPOSITORY) {
addAdministratorOnlyButton(tableRow.addCell(), "submit_create_wf_role_" + roleId, T_create);
} else {
tableRow.addCell();
}
}
// help and directions row
tableRow = rolesTable.addRow(Row.ROLE_DATA);
@@ -379,6 +399,19 @@ public class AssignCollectionRoles extends AbstractDSpaceTransformer
tableRow.addCell(1,2).addHighlight("fade offset").addContent(role.getDescription());
}
} else {
tableRow = rolesTable.addRow(Row.ROLE_DATA);
tableRow.addCell(Cell.ROLE_HEADER).addContent(role.getName());
tableRow.addCell().addContent(T_no_role);
tableRow.addCell();
// help and directions row
tableRow = rolesTable.addRow(Row.ROLE_DATA);
tableRow.addCell();
if (role.getDescription() != null){
tableRow.addCell(1,2).addHighlight("fade offset").addContent(role.getDescription());
}
}
}
}

View File

@@ -232,7 +232,7 @@ public abstract class AbstractStep extends AbstractDSpaceTransformer
HandleUtil.buildHandleTrail(collection,pageMeta,contextPath, true);
pageMeta.addTrail().addContent(T_submission_trail);
}
else if (submission instanceof WorkflowItem)
else if (submissionInfo != null && submissionInfo.isInWorkflow())
{
pageMeta.addMetadata("title").addContent(T_workflow_title);

View File

@@ -37,6 +37,7 @@ import org.dspace.content.BitstreamFormat;
import org.dspace.content.Bundle;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.core.ConfigurationManager;
import org.dspace.workflow.WorkflowItem;
import org.xml.sax.SAXException;
@@ -166,7 +167,7 @@ public class UploadStep extends AbstractSubmissionStep
Item item = submission.getItem();
Collection collection = submission.getCollection();
String actionURL = contextPath + "/handle/"+collection.getHandle() + "/submit/" + knot.getId() + ".continue";
boolean workflow = submission instanceof WorkflowItem;
boolean disableFileEditing = (submissionInfo.isInWorkflow()) && !ConfigurationManager.getBooleanProperty("workflow", "reviewer.file-edit");
Bundle[] bundles = item.getBundles("ORIGINAL");
Bitstream[] bitstreams = new Bitstream[0];
if (bundles.length > 0)
@@ -182,7 +183,7 @@ public class UploadStep extends AbstractSubmissionStep
List upload = null;
if (!workflow)
if (!disableFileEditing)
{
// Only add the upload capabilities for new item submissions
upload = div.addList("submit-upload-new", List.TYPE_FORM);
@@ -227,7 +228,7 @@ public class UploadStep extends AbstractSubmissionStep
// Part B:
// If the user has already uploaded files provide a list for the user.
if (bitstreams.length > 0 || workflow)
if (bitstreams.length > 0 || disableFileEditing)
{
Table summary = div.addTable("submit-upload-summary",(bitstreams.length * 2) + 2,7);
summary.setHead(T_head2);
@@ -264,7 +265,7 @@ public class UploadStep extends AbstractSubmissionStep
primary.setOptionSelected(String.valueOf(id));
}
if (!workflow)
if (!disableFileEditing)
{
// Workflow users can not remove files.
CheckBox remove = row.addCell().addCheckBox("remove");
@@ -323,7 +324,7 @@ public class UploadStep extends AbstractSubmissionStep
checksumCell.addContent(algorithm + ":" + checksum);
}
if (!workflow)
if (!disableFileEditing)
{
// Workflow users can not remove files.
Row actionRow = summary.addRow();

View File

@@ -159,7 +159,8 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep
isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false);
}
public void addPageMeta(PageMeta pageMeta) throws WingException{
public void addPageMeta(PageMeta pageMeta) throws WingException, AuthorizeException, IOException, SAXException, SQLException {
super.addPageMeta(pageMeta);
pageMeta.addMetadata("javascript", "static").addContent("static/js/accessFormUtil.js");
}
@@ -186,7 +187,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep
Item item = submission.getItem();
Collection collection = submission.getCollection();
String actionURL = contextPath + "/handle/"+collection.getHandle() + "/submit/" + knot.getId() + ".continue";
boolean workflow = submission instanceof WorkflowItem;
boolean disableFileEditing = (submissionInfo.isInWorkflow()) && !ConfigurationManager.getBooleanProperty("workflow", "reviewer.file-edit");
Bundle[] bundles = item.getBundles("ORIGINAL");
Bitstream[] bitstreams = new Bitstream[0];
if (bundles.length > 0)
@@ -202,7 +203,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep
List upload = null;
if (!workflow)
if (!disableFileEditing)
{
// Only add the upload capabilities for new item submissions
upload = div.addList("submit-upload-new", List.TYPE_FORM);
@@ -257,7 +258,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep
// Part B:
// If the user has already uploaded files provide a list for the user.
if (bitstreams.length > 0 || workflow)
if (bitstreams.length > 0 || disableFileEditing)
{
Table summary = div.addTable("submit-upload-summary",(bitstreams.length * 2) + 2,7);
summary.setHead(T_head2);
@@ -294,7 +295,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep
primary.setOptionSelected(String.valueOf(id));
}
if (!workflow)
if (!disableFileEditing)
{
// Workflow users can not remove files.
CheckBox remove = row.addCell().addCheckBox("remove");
@@ -358,7 +359,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep
checksumCell.addContent(algorithm + ":" + checksum);
}
if (!workflow)
if (!disableFileEditing)
{
// Workflow users can not remove files.
Row actionRow = summary.addRow();

View File

@@ -1599,6 +1599,7 @@
<message key="xmlui.administrative.collection.AssignCollectionRoles.label_submitters">Submitters</message>
<message key="xmlui.administrative.collection.AssignCollectionRoles.label_default_read">Default read access</message>
<message key="xmlui.administrative.collection.AssignCollectionRoles.sysadmins_only"><nobr>(system administrators only)</nobr></message>
<message key="xmlui.administrative.collection.AssignCollectionRoles.repository_role"><br/>(Repository level group, system administrators only)</message>
<message key="xmlui.administrative.collection.AssignCollectionRoles.not_allowed"><nobr>(you are not allowed to configure this)</nobr></message>
<!-- org.dspace.app.xmlui.administrative.collection.CurateCollectionForm.java -->

View File

@@ -14,7 +14,7 @@
<!ATTLIST form name NMTOKEN #REQUIRED>
<!ELEMENT page (field)+ >
<!ATTLIST page number NMTOKEN #REQUIRED>
<!ELEMENT field (dc-schema, dc-element, dc-qualifier?, repeatable?, label, input-type, hint, required?, vocabulary?) >
<!ELEMENT field (dc-schema, dc-element, dc-qualifier?, repeatable?, label, input-type, hint, required?, vocabulary?, visibility?) >
<!ELEMENT dc-schema (#PCDATA) >
<!ELEMENT dc-element (#PCDATA) >
<!ELEMENT dc-qualifier (#PCDATA) >
@@ -51,3 +51,5 @@
<!ELEMENT vocabulary (#PCDATA) >
<!ATTLIST vocabulary closed (true|false) "false">
<!ELEMENT visibility (#PCDATA) >

View File

@@ -10,3 +10,7 @@
# xmlworkflow = New (as of 1.8.0) Configurable Reviewer Workflow
workflow.framework=originalworkflow
#workflow.framework=xmlworkflow
#Allow the reviewers to add/edit/remove files from the submission
#When changing this property you might want to alert submitters in the license that reviewers can alter their files
reviewer.file-edit=false