diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index e4feb86a3f..f4bbdadd04 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -7,6 +7,15 @@ */ 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.lang.StringUtils; import org.apache.log4j.Logger; @@ -18,7 +27,15 @@ import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.authority.Choices; 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.Context; import org.dspace.core.LogManager; @@ -29,15 +46,11 @@ import org.dspace.harvest.HarvestedItem; import org.dspace.harvest.service.HarvestedItemService; import org.dspace.identifier.IdentifierException; import org.dspace.identifier.service.IdentifierService; +import org.dspace.services.ConfigurationService; import org.dspace.versioning.service.VersioningService; import org.dspace.workflow.WorkflowItemService; 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. * 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 implements It protected VersioningService versioningService; @Autowired(required=true) protected HarvestedItemService harvestedItemService; + @Autowired(required=true) + protected ConfigurationService configurationService; + @Autowired(required=true) protected WorkspaceItemService workspaceItemService; @Autowired(required=true) @@ -596,13 +612,15 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It context.addEvent(new Event(Event.DELETE, Constants.ITEM, item.getID(), item.getHandle(), getIdentifiers(context, item))); - log.info(LogManager.getHeader(context, "delete_item", "item_id=" + item.getID())); // Remove bundles removeAllBundles(context, item); + // Remove any Handle + handleService.unbindHandle(context, item); + // remove version attached to the item removeVersion(context, item); @@ -618,10 +636,6 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It item.getCollections().clear(); item.setOwningCollection(null); - // Remove any Handle - handleService.unbindHandle(context, item); - - // Finally remove item row 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 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; + } } diff --git a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java index 1dda8eb6d3..bf44b340c4 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java @@ -444,7 +444,15 @@ public interface ItemService extends DSpaceObjectService, DSpaceObjectLega * @throws SQLException if database error */ 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 * those matching the passed value, if value is not Item.ANY diff --git a/dspace-api/src/main/java/org/dspace/versioning/AbstractVersionProvider.java b/dspace-api/src/main/java/org/dspace/versioning/AbstractVersionProvider.java index ad286af559..5977e80715 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/AbstractVersionProvider.java +++ b/dspace-api/src/main/java/org/dspace/versioning/AbstractVersionProvider.java @@ -96,18 +96,19 @@ public abstract class AbstractVersionProvider { { 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); List bitstreamMeta = bitstreamService.getMetadata(nativeBitstream, Item.ANY, Item.ANY, Item.ANY, Item.ANY); for (MetadataValue value : bitstreamMeta) { bitstreamService.addMetadata(context, newBitstream, value.getMetadataField(), value.getLanguage(), value.getValue(), value.getAuthority(), value.getConfidence()); } - bitstreamService.update(context, newBitstream); return newBitstream; } diff --git a/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java b/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java index 54c6ca6cb3..83610e9947 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java +++ b/dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.log4j.Logger; import org.dspace.authorize.ResourcePolicy; import org.dspace.versioning.service.VersioningService; +import org.dspace.workflow.WorkflowItemService; /** * @@ -39,6 +40,8 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen @Autowired(required = true) protected WorkspaceItemService workspaceItemService; @Autowired(required = true) + protected WorkflowItemService workflowItemService; + @Autowired(required = true) protected VersionHistoryService versionHistoryService; @Autowired(required = true) protected VersioningService versioningService; @@ -69,10 +72,20 @@ public class DefaultItemVersionProvider extends AbstractVersionProvider implemen if(versionHistoryService.isLastVersion(c, history, versionToDelete) && 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.setArchived(true); - itemService.update(c, item); + if (!item.isArchived() + || 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 diff --git a/dspace-api/src/main/java/org/dspace/versioning/VersioningServiceImpl.java b/dspace-api/src/main/java/org/dspace/versioning/VersioningServiceImpl.java index 07af435a3a..1ab4cde711 100644 --- a/dspace-api/src/main/java/org/dspace/versioning/VersioningServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/versioning/VersioningServiceImpl.java @@ -7,22 +7,25 @@ */ 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.MetadataValue; 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.WorkspaceItemService; import org.dspace.core.Context; import org.dspace.versioning.dao.VersionDAO; import org.dspace.versioning.service.VersionHistoryService; 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.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; @Autowired(required = true) private ItemService itemService; + @Autowired(required = true) + private WorkspaceItemService workspaceItemService; + @Autowired(required = true) + protected WorkflowItemService workflowItemService; + private DefaultItemVersionProvider provider; @Required @@ -129,7 +137,24 @@ public class VersioningServiceImpl implements VersioningService { // Completely delete the item 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) { c.abort(); diff --git a/dspace-api/src/main/resources/Messages.properties b/dspace-api/src/main/resources/Messages.properties index c2c95896de..e7e00aa313 100644 --- a/dspace-api/src/main/resources/Messages.properties +++ b/dspace-api/src/main/resources/Messages.properties @@ -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.question = Are you sure you want to proceed with the changes? jsp.submit.verify-prune.title = Answers to Initial Questions Changed +jsp.submittertools = Actions jsp.suggest.button.cancel = Cancel jsp.suggest.button.send = Send Recommendation jsp.suggest.heading = Recommended Item: diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/components/VersioningItemHome.java b/dspace-jspui/src/main/java/org/dspace/app/webui/components/VersioningItemHome.java index ab66337c2f..1d761802b1 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/components/VersioningItemHome.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/components/VersioningItemHome.java @@ -13,7 +13,6 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; 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.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; -import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; import org.dspace.handle.factory.HandleServiceFactory; 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.plugin.ItemHomeProcessor; 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.VersionHistory; import org.dspace.versioning.factory.VersionServiceFactory; @@ -48,7 +48,8 @@ public class VersioningItemHome implements ItemHomeProcessor { private IdentifierService identifierService; private VersionHistoryService versionHistoryService; private VersioningService versioningService; - private ItemService itemService; + private ItemService itemService; + private ConfigurationService configurationService; public VersioningItemHome() { doiService = IdentifierServiceFactory.getInstance().getDOIService(); @@ -57,6 +58,7 @@ public class VersioningItemHome implements ItemHomeProcessor { itemService = ContentServiceFactory.getInstance().getItemService(); versioningService = VersionServiceFactory.getInstance().getVersionService(); versionHistoryService = VersionServiceFactory.getInstance().getVersionHistoryService(); + configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); } @@ -64,8 +66,10 @@ public class VersioningItemHome implements ItemHomeProcessor { public void process(Context context, HttpServletRequest request, HttpServletResponse response, Item item) throws PluginException, AuthorizeException { - boolean versioningEnabled = ConfigurationManager.getBooleanProperty( - "versioning", "enabled"); + boolean versioningEnabled = configurationService + .getPropertyAsType("versioning.enabled", false); + boolean submitterCanCreateNewVersion = configurationService + .getPropertyAsType("versioning.submitterCanCreateNewVersion", false); boolean newVersionAvailable = false; boolean showVersionWorkflowAvailable = false; boolean hasVersionButton = false; @@ -81,7 +85,17 @@ public class VersioningItemHome implements ItemHomeProcessor { if (versionHistoryService.isLastVersion(context, item) && item.isArchived()) { hasVersionButton = true; - } + } + } + else if (submitterCanCreateNewVersion) + { + if (versionHistoryService.isLastVersion(context, item) + && item.isArchived() + && itemService.canCreateNewVersion(context, item)) + { + hasVersionButton = true; + } + } if (versionHistoryService.hasVersionHistory(context, item)) { hasVersionHistory = true; @@ -139,7 +153,7 @@ public class VersioningItemHome implements ItemHomeProcessor { } // 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) { diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/HandleServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/HandleServlet.java index f39f0d9e3d..6c87d4c0b5 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/HandleServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/HandleServlet.java @@ -389,8 +389,14 @@ public class HandleServlet extends DSpaceServlet { // set a variable to create an edit button 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 List collections = item.getCollections(); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java index 016ea4c0b7..88dcc155eb 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java @@ -92,7 +92,8 @@ public class VersionUtil Item item = itemService.find(context, itemID); 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() .getSingletonService(VersioningService.class); @@ -198,10 +199,11 @@ public class VersionUtil { Item item = itemService.find(context, itemId); 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 diff --git a/dspace-jspui/src/main/webapp/display-item.jsp b/dspace-jspui/src/main/webapp/display-item.jsp index c119894b00..a948725fc3 100644 --- a/dspace-jspui/src/main/webapp/display-item.jsp +++ b/dspace-jspui/src/main/webapp/display-item.jsp @@ -22,6 +22,7 @@ - appear yet. If this is omitted, the item display won't - display any collections. - admin_button - Boolean, show admin 'edit' button + - submitter_button - Boolean, show submitter "new version" button --%> <%@page contentType="text/html;charset=UTF-8" %> @@ -64,7 +65,8 @@ List collections = (List) request.getAttribute("collections"); Boolean admin_b = (Boolean)request.getAttribute("admin_button"); 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 Integer workspace_id = (Integer) request.getAttribute("workspace_id"); @@ -198,6 +200,22 @@ <% } %> <% + // submitter create new version button + if (submitter_button && hasVersionButton) { +%> + +
+
+
+
+ + " /> +
+
+
+
+<% + } } String displayStyle = (displayAll ? "full" : ""); diff --git a/dspace/config/modules/versioning.cfg b/dspace/config/modules/versioning.cfg index 62e644f8b0..2dbce7f2a1 100644 --- a/dspace/config/modules/versioning.cfg +++ b/dspace/config/modules/versioning.cfg @@ -14,3 +14,8 @@ versioning.item.history.view.admin=false # the submitter of a version should be included in the version history of # an item. 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