Merge pull request #896 from tuub/DS-1814

DS-1814: Allow submitter to create new version of their items.
This commit is contained in:
Tim Donohue
2016-08-31 15:49:08 -05:00
committed by GitHub
11 changed files with 161 additions and 37 deletions

View File

@@ -7,6 +7,15 @@
*/ */
package org.dspace.content; package org.dspace.content;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@@ -18,7 +27,15 @@ import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.content.authority.Choices; import org.dspace.content.authority.Choices;
import org.dspace.content.dao.ItemDAO; import org.dspace.content.dao.ItemDAO;
import org.dspace.content.service.*; import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BundleService;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.MetadataSchemaService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogManager; import org.dspace.core.LogManager;
@@ -29,15 +46,11 @@ import org.dspace.harvest.HarvestedItem;
import org.dspace.harvest.service.HarvestedItemService; import org.dspace.harvest.service.HarvestedItemService;
import org.dspace.identifier.IdentifierException; import org.dspace.identifier.IdentifierException;
import org.dspace.identifier.service.IdentifierService; import org.dspace.identifier.service.IdentifierService;
import org.dspace.services.ConfigurationService;
import org.dspace.versioning.service.VersioningService; import org.dspace.versioning.service.VersioningService;
import org.dspace.workflow.WorkflowItemService; import org.dspace.workflow.WorkflowItemService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;
/** /**
* Service implementation for the Item object. * Service implementation for the Item object.
* This class is responsible for all business logic calls for the Item object and is autowired by spring. * This class is responsible for all business logic calls for the Item object and is autowired by spring.
@@ -79,6 +92,9 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
protected VersioningService versioningService; protected VersioningService versioningService;
@Autowired(required=true) @Autowired(required=true)
protected HarvestedItemService harvestedItemService; protected HarvestedItemService harvestedItemService;
@Autowired(required=true)
protected ConfigurationService configurationService;
@Autowired(required=true) @Autowired(required=true)
protected WorkspaceItemService workspaceItemService; protected WorkspaceItemService workspaceItemService;
@Autowired(required=true) @Autowired(required=true)
@@ -596,13 +612,15 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
context.addEvent(new Event(Event.DELETE, Constants.ITEM, item.getID(), context.addEvent(new Event(Event.DELETE, Constants.ITEM, item.getID(),
item.getHandle(), getIdentifiers(context, item))); item.getHandle(), getIdentifiers(context, item)));
log.info(LogManager.getHeader(context, "delete_item", "item_id=" log.info(LogManager.getHeader(context, "delete_item", "item_id="
+ item.getID())); + item.getID()));
// Remove bundles // Remove bundles
removeAllBundles(context, item); removeAllBundles(context, item);
// Remove any Handle
handleService.unbindHandle(context, item);
// remove version attached to the item // remove version attached to the item
removeVersion(context, item); removeVersion(context, item);
@@ -618,10 +636,6 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
item.getCollections().clear(); item.getCollections().clear();
item.setOwningCollection(null); item.setOwningCollection(null);
// Remove any Handle
handleService.unbindHandle(context, item);
// Finally remove item row // Finally remove item row
itemDAO.delete(context, item); itemDAO.delete(context, item);
} }
@@ -1213,4 +1227,21 @@ prevent the generation of resource policy entry values with null dspace_object a
// return count of items that are not in archive and withdrawn // return count of items that are not in archive and withdrawn
return itemDAO.countItems(context, false, true); return itemDAO.countItems(context, false, true);
} }
@Override
public boolean canCreateNewVersion(Context context, Item item) throws SQLException{
if (authorizeService.isAdmin(context, item))
{
return true;
}
if (context.getCurrentUser() != null
&& context.getCurrentUser().equals(item.getSubmitter()))
{
return configurationService.getPropertyAsType(
"versioning.submitterCanCreateNewVersion", false);
}
return false;
}
} }

View File

@@ -444,7 +444,15 @@ public interface ItemService extends DSpaceObjectService<Item>, DSpaceObjectLega
* @throws SQLException if database error * @throws SQLException if database error
*/ */
public boolean canEdit(Context context, Item item) throws java.sql.SQLException; public boolean canEdit(Context context, Item item) throws java.sql.SQLException;
/**
* return TRUE if context's user can create new version of the item, false
* otherwise.
* @return boolean true = current user can create new version of the item
* @throws SQLException
*/
public boolean canCreateNewVersion(Context context, Item item) throws SQLException;
/** /**
* Returns an iterator of Items possessing the passed metadata field, or only * Returns an iterator of Items possessing the passed metadata field, or only
* those matching the passed value, if value is not Item.ANY * those matching the passed value, if value is not Item.ANY

View File

@@ -96,18 +96,19 @@ public abstract class AbstractVersionProvider {
{ {
bundleNew.setPrimaryBitstreamID(bitstreamNew); bundleNew.setPrimaryBitstreamID(bitstreamNew);
} }
bitstreamService.update(c, bitstreamNew);
} }
} }
} }
protected Bitstream createBitstream(Context context, Bitstream nativeBitstream) throws AuthorizeException, SQLException, IOException { protected Bitstream createBitstream(Context context, Bitstream nativeBitstream) throws AuthorizeException, SQLException, IOException {
Bitstream newBitstream = bitstreamStorageService.clone(context, nativeBitstream); Bitstream newBitstream = bitstreamStorageService.clone(context, nativeBitstream);
List<MetadataValue> bitstreamMeta = bitstreamService.getMetadata(nativeBitstream, Item.ANY, Item.ANY, Item.ANY, Item.ANY); List<MetadataValue> bitstreamMeta = bitstreamService.getMetadata(nativeBitstream, Item.ANY, Item.ANY, Item.ANY, Item.ANY);
for (MetadataValue value : bitstreamMeta) { for (MetadataValue value : bitstreamMeta) {
bitstreamService.addMetadata(context, newBitstream, value.getMetadataField(), value.getLanguage(), value.getValue(), value.getAuthority(), value.getConfidence()); bitstreamService.addMetadata(context, newBitstream, value.getMetadataField(), value.getLanguage(), value.getValue(), value.getAuthority(), value.getConfidence());
} }
bitstreamService.update(context, newBitstream);
return newBitstream; return newBitstream;
} }

View File

@@ -23,6 +23,7 @@ import java.util.List;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy;
import org.dspace.versioning.service.VersioningService; import org.dspace.versioning.service.VersioningService;
import org.dspace.workflow.WorkflowItemService;
/** /**
* *
@@ -39,6 +40,8 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen
@Autowired(required = true) @Autowired(required = true)
protected WorkspaceItemService workspaceItemService; protected WorkspaceItemService workspaceItemService;
@Autowired(required = true) @Autowired(required = true)
protected WorkflowItemService workflowItemService;
@Autowired(required = true)
protected VersionHistoryService versionHistoryService; protected VersionHistoryService versionHistoryService;
@Autowired(required = true) @Autowired(required = true)
protected VersioningService versioningService; protected VersioningService versioningService;
@@ -69,10 +72,20 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen
if(versionHistoryService.isLastVersion(c, history, versionToDelete) if(versionHistoryService.isLastVersion(c, history, versionToDelete)
&& versioningService.getVersionsByHistory(c, history).size() > 1) && versioningService.getVersionsByHistory(c, history).size() > 1)
{ {
// reset the previous version to archived // if a new version gets archived, the old one is set to false.
// we need to do the oposite now, if the old version was previously
// unarchived. If the old version is still archived, the new
// version is a WorkspaceItem or WorkflowItem we should skip this,
// as unarchiving of previous versions is done only when a newer
// version gets archived.
Item item = versionHistoryService.getPrevious(c, history, versionToDelete).getItem(); Item item = versionHistoryService.getPrevious(c, history, versionToDelete).getItem();
item.setArchived(true); if (!item.isArchived()
itemService.update(c, item); || workspaceItemService.findByItem(c, versionToDelete.getItem()) != null
|| workflowItemService.findByItem(c, versionToDelete.getItem()) != null)
{
item.setArchived(true);
itemService.update(c, item);
}
} }
// assign tombstone to the Identifier and reset canonical to the previous version only if there is a previous version // assign tombstone to the Identifier and reset canonical to the previous version only if there is a previous version

View File

@@ -7,22 +7,25 @@
*/ */
package org.dspace.versioning; package org.dspace.versioning;
import org.apache.commons.collections.CollectionUtils; import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import org.dspace.content.DCDate; import org.dspace.content.DCDate;
import org.dspace.content.MetadataValue;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataValue;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.versioning.dao.VersionDAO; import org.dspace.versioning.dao.VersionDAO;
import org.dspace.versioning.service.VersionHistoryService; import org.dspace.versioning.service.VersionHistoryService;
import org.dspace.versioning.service.VersioningService; import org.dspace.versioning.service.VersioningService;
import org.dspace.workflow.WorkflowItem;
import org.dspace.workflow.WorkflowItemService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.annotation.Required;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
/** /**
* *
* *
@@ -39,6 +42,11 @@ public class VersioningServiceImpl implements VersioningService {
protected VersionDAO versionDAO; protected VersionDAO versionDAO;
@Autowired(required = true) @Autowired(required = true)
private ItemService itemService; private ItemService itemService;
@Autowired(required = true)
private WorkspaceItemService workspaceItemService;
@Autowired(required = true)
protected WorkflowItemService workflowItemService;
private DefaultItemVersionProvider provider; private DefaultItemVersionProvider provider;
@Required @Required
@@ -129,7 +137,24 @@ public class VersioningServiceImpl implements VersioningService {
// Completely delete the item // Completely delete the item
if (item != null) { if (item != null) {
itemService.delete(c, item); // DS-1814 introduce the possibility that submitter can create
// new versions. To avoid authorithation problems we need to
// check whether a corresponding workspaceItem exists.
if (!item.isArchived())
{
WorkspaceItem wsi = workspaceItemService.findByItem(c, item);
if(wsi != null) {
workspaceItemService.deleteAll(c, wsi);
} else {
WorkflowItem wfi = workflowItemService.findByItem(c, item);
if (wfi != null) {
workflowItemService.delete(c, wfi);
}
}
}
else {
itemService.delete(c, item);
}
} }
}catch (Exception e) { }catch (Exception e) {
c.abort(); c.abort();

View File

@@ -1196,6 +1196,7 @@ jsp.submit.verify-prune.notproceed.button = Do Not Make th
jsp.submit.verify-prune.proceed.button = Proceed With Changes jsp.submit.verify-prune.proceed.button = Proceed With Changes
jsp.submit.verify-prune.question = Are you sure you want to proceed with the changes? jsp.submit.verify-prune.question = Are you sure you want to proceed with the changes?
jsp.submit.verify-prune.title = Answers to Initial Questions Changed jsp.submit.verify-prune.title = Answers to Initial Questions Changed
jsp.submittertools = Actions
jsp.suggest.button.cancel = Cancel jsp.suggest.button.cancel = Cancel
jsp.suggest.button.send = Send Recommendation jsp.suggest.button.send = Send Recommendation
jsp.suggest.heading = Recommended Item: jsp.suggest.heading = Recommended Item:

View File

@@ -13,7 +13,6 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.webui.util.VersionUtil; import org.dspace.app.webui.util.VersionUtil;
@@ -21,7 +20,6 @@ import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.core.ConfigurationManager;
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;
@@ -32,6 +30,8 @@ import org.dspace.identifier.service.DOIService;
import org.dspace.identifier.service.IdentifierService; import org.dspace.identifier.service.IdentifierService;
import org.dspace.plugin.ItemHomeProcessor; import org.dspace.plugin.ItemHomeProcessor;
import org.dspace.plugin.PluginException; import org.dspace.plugin.PluginException;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.versioning.Version; import org.dspace.versioning.Version;
import org.dspace.versioning.VersionHistory; import org.dspace.versioning.VersionHistory;
import org.dspace.versioning.factory.VersionServiceFactory; import org.dspace.versioning.factory.VersionServiceFactory;
@@ -48,7 +48,8 @@ public class VersioningItemHome implements ItemHomeProcessor {
private IdentifierService identifierService; private IdentifierService identifierService;
private VersionHistoryService versionHistoryService; private VersionHistoryService versionHistoryService;
private VersioningService versioningService; private VersioningService versioningService;
private ItemService itemService; private ItemService itemService;
private ConfigurationService configurationService;
public VersioningItemHome() { public VersioningItemHome() {
doiService = IdentifierServiceFactory.getInstance().getDOIService(); doiService = IdentifierServiceFactory.getInstance().getDOIService();
@@ -57,6 +58,7 @@ public class VersioningItemHome implements ItemHomeProcessor {
itemService = ContentServiceFactory.getInstance().getItemService(); itemService = ContentServiceFactory.getInstance().getItemService();
versioningService = VersionServiceFactory.getInstance().getVersionService(); versioningService = VersionServiceFactory.getInstance().getVersionService();
versionHistoryService = VersionServiceFactory.getInstance().getVersionHistoryService(); versionHistoryService = VersionServiceFactory.getInstance().getVersionHistoryService();
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
} }
@@ -64,8 +66,10 @@ public class VersioningItemHome implements ItemHomeProcessor {
public void process(Context context, HttpServletRequest request, public void process(Context context, HttpServletRequest request,
HttpServletResponse response, Item item) throws PluginException, HttpServletResponse response, Item item) throws PluginException,
AuthorizeException { AuthorizeException {
boolean versioningEnabled = ConfigurationManager.getBooleanProperty( boolean versioningEnabled = configurationService
"versioning", "enabled"); .getPropertyAsType("versioning.enabled", false);
boolean submitterCanCreateNewVersion = configurationService
.getPropertyAsType("versioning.submitterCanCreateNewVersion", false);
boolean newVersionAvailable = false; boolean newVersionAvailable = false;
boolean showVersionWorkflowAvailable = false; boolean showVersionWorkflowAvailable = false;
boolean hasVersionButton = false; boolean hasVersionButton = false;
@@ -81,7 +85,17 @@ public class VersioningItemHome implements ItemHomeProcessor {
if (versionHistoryService.isLastVersion(context, item) if (versionHistoryService.isLastVersion(context, item)
&& item.isArchived()) { && item.isArchived()) {
hasVersionButton = true; hasVersionButton = true;
} }
}
else if (submitterCanCreateNewVersion)
{
if (versionHistoryService.isLastVersion(context, item)
&& item.isArchived()
&& itemService.canCreateNewVersion(context, item))
{
hasVersionButton = true;
}
} }
if (versionHistoryService.hasVersionHistory(context, item)) { if (versionHistoryService.hasVersionHistory(context, item)) {
hasVersionHistory = true; hasVersionHistory = true;
@@ -139,7 +153,7 @@ public class VersioningItemHome implements ItemHomeProcessor {
} }
// do we prefer to use handle or DOIs? // do we prefer to use handle or DOIs?
if ("doi".equalsIgnoreCase(ConfigurationManager.getProperty("webui.preferred.identifier"))) if ("doi".equalsIgnoreCase(configurationService.getProperty("webui.preferred.identifier")))
{ {
if (latestVersionDOI != null) if (latestVersionDOI != null)
{ {

View File

@@ -389,8 +389,14 @@ public class HandleServlet extends DSpaceServlet
{ {
// set a variable to create an edit button // set a variable to create an edit button
request.setAttribute("admin_button", Boolean.TRUE); request.setAttribute("admin_button", Boolean.TRUE);
}
// show submitters a button to create a new item version
else if (itemService.canCreateNewVersion(context, item))
{
// set a variable to create a button to create a new item version
request.setAttribute("submitter_button", Boolean.TRUE);
} }
// Get the collections // Get the collections
List<Collection> collections = item.getCollections(); List<Collection> collections = item.getCollections();

View File

@@ -92,7 +92,8 @@ public class VersionUtil
Item item = itemService.find(context, itemID); Item item = itemService.find(context, itemID);
if (authorizeService.authorizeActionBoolean(context, item, if (authorizeService.authorizeActionBoolean(context, item,
Constants.WRITE) || itemService.canEdit(context, item)) Constants.WRITE) || itemService.canEdit(context, item)
|| itemService.canCreateNewVersion(context, item))
{ {
VersioningService versioningService = new DSpace() VersioningService versioningService = new DSpace()
.getSingletonService(VersioningService.class); .getSingletonService(VersioningService.class);
@@ -198,10 +199,11 @@ public class VersionUtil
{ {
Item item = itemService.find(context, itemId); Item item = itemService.find(context, itemId);
VersionHistory versionHistory = versionHistoryService.findByItem(context, item); VersionHistory versionHistory = versionHistoryService.findByItem(context, item);
for (String id : versionIDs) for (String versionID : versionIDs)
{ {
versioningService.removeVersion(context, item); Version version = versioningService.getVersion(context, Integer.parseInt(versionID));
versioningService.removeVersion(context, version);
} }
// Retrieve the latest version of our history (IF any is even // Retrieve the latest version of our history (IF any is even

View File

@@ -22,6 +22,7 @@
- appear yet. If this is omitted, the item display won't - appear yet. If this is omitted, the item display won't
- display any collections. - display any collections.
- admin_button - Boolean, show admin 'edit' button - admin_button - Boolean, show admin 'edit' button
- submitter_button - Boolean, show submitter "new version" button
--%> --%>
<%@page contentType="text/html;charset=UTF-8" %> <%@page contentType="text/html;charset=UTF-8" %>
@@ -64,7 +65,8 @@
List<Collection> collections = (List<Collection>) request.getAttribute("collections"); List<Collection> collections = (List<Collection>) request.getAttribute("collections");
Boolean admin_b = (Boolean)request.getAttribute("admin_button"); Boolean admin_b = (Boolean)request.getAttribute("admin_button");
boolean admin_button = (admin_b == null ? false : admin_b.booleanValue()); boolean admin_button = (admin_b == null ? false : admin_b.booleanValue());
Boolean submitter_b = (Boolean) request.getAttribute("submitter_button");
boolean submitter_button = (submitter_b == null ? false : submitter_b.booleanValue());
// get the workspace id if one has been passed // get the workspace id if one has been passed
Integer workspace_id = (Integer) request.getAttribute("workspace_id"); Integer workspace_id = (Integer) request.getAttribute("workspace_id");
@@ -198,6 +200,22 @@
<% } %> <% } %>
<% <%
// submitter create new version button
if (submitter_button && hasVersionButton) {
%>
<dspace:sidebar>
<div class="panel panel-warning">
<div class="panel-heading"><fmt:message key="jsp.submittertools"/></div>
<div class="panel-body">
<form method="get" action="<%= request.getContextPath()%>/tools/version">
<input type="hidden" name="itemID" value="<%= item.getID()%>" />
<input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.general.version.button"/>" />
</form>
</div>
</div>
</dspace:sidebar>
<%
}
} }
String displayStyle = (displayAll ? "full" : ""); String displayStyle = (displayAll ? "full" : "");

View File

@@ -14,3 +14,8 @@ versioning.item.history.view.admin=false
# the submitter of a version should be included in the version history of # the submitter of a version should be included in the version history of
# an item. # an item.
versioning.item.history.include.submitter=false versioning.item.history.include.submitter=false
# If you want to allow submitters to create new versions of there items, set
# the property submitterCanCreateNewVersion true. This is currently supported
# by JSPUI only.
# versioning.submitterCanCreateNewVersion=false