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

@@ -86,7 +86,7 @@ public class UsageEvent extends Event {
return objText + ":" + action.text();
}catch(Exception e)
{
}
return "";

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,9 +209,13 @@ 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);
ass.delete();
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();
}
}
@@ -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,17 +488,23 @@ 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);
roleGroup.setName("COLLECTION_" + collection.getID() + "_WORKFLOW_ROLE_" + roleName);
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);
WorkflowUtils.createCollectionWorkflowRole(context, collectionID, roleName, roleGroup);
}
if(role.getScope() == Role.Scope.COLLECTION){
WorkflowUtils.createCollectionWorkflowRole(context, collectionID, roleName, roleGroup);
}
}
}
return roleGroup;
}
@@ -513,8 +519,8 @@ 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();
Collection collection = Collection.find(context,collectionID);
@@ -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) {
tableRow.addCell().addXref(baseURL + "&submit_edit_wf_role_" + roleId, roleGroup.getName());
addAdministratorOnlyButton(tableRow.addCell(), "submit_delete_wf_role_" + roleId, T_delete);
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);
addAdministratorOnlyButton(tableRow.addCell(), "submit_create_wf_role_" + roleId, T_create);
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