Merged dspace/master into configurable_entities

This commit is contained in:
Raf Ponsaerts
2019-04-05 13:45:01 +02:00
166 changed files with 7908 additions and 900 deletions

View File

@@ -0,0 +1,52 @@
/**
* 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/
*/
package org.dspace.browse;
import java.io.Serializable;
import org.dspace.core.Constants;
/**
* This is the basic interface that a data model entity need to implement to support browsing/retrieval
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*
* @param <PK>
* the Class of the primary key
*/
public interface BrowsableObject<PK extends Serializable> {
/**
*
* @return the integer constant representing the Entity Type, @see {@link Constants}
*/
public int getType();
/**
*
* @return the primary key of the Entity instance
*/
public PK getID();
/**
*
* @return an unique id to index
*/
default String getUniqueIndexID() {
return getType() + "-" + getID().toString();
}
/**
*
* @return a textual alias of the Entity Type @see {@link #getType()}
*/
default public String getTypeText() {
return Constants.typeText[getType()];
};
}

View File

@@ -11,6 +11,7 @@ import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -21,6 +22,7 @@ import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.apache.log4j.Logger;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamService;
import org.dspace.core.Constants;
@@ -40,6 +42,12 @@ import org.hibernate.proxy.HibernateProxyHelper;
@Entity
@Table(name = "bitstream")
public class Bitstream extends DSpaceObject implements DSpaceObjectLegacySupport {
/**
* log4j logger
*/
private static Logger log = Logger.getLogger(Bitstream.class);
@Column(name = "bitstream_id", insertable = false, updatable = false)
private Integer legacyId;

View File

@@ -12,6 +12,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -71,23 +72,6 @@ public class Collection extends DSpaceObject implements DSpaceObjectLegacySuppor
@JoinColumn(name = "template_item_id")
private Item template;
/**
* Groups corresponding to workflow steps - NOTE these start from one, so
* workflowGroups[0] corresponds to workflow_step_1.
*/
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "workflow_step_1")
private Group workflowStep1;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "workflow_step_2")
private Group workflowStep2;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "workflow_step_3")
private Group workflowStep3;
@OneToOne
@JoinColumn(name = "submitter")
/** The default group of administrators */
@@ -202,31 +186,22 @@ public class Collection extends DSpaceObject implements DSpaceObjectLegacySuppor
setModified();
}
public Group getWorkflowStep1() {
return workflowStep1;
// FIXME this should be moved to the collectionService or completely removed, see also
// https://jira.duraspace.org/browse/DS-3041
public Group getWorkflowStep1(Context context) {
return getCollectionService().getWorkflowGroup(context, this, 1);
}
public Group getWorkflowStep2() {
return workflowStep2;
// FIXME this should be moved to the collectionService or completely removed, see also
// https://jira.duraspace.org/browse/DS-3041
public Group getWorkflowStep2(Context context) {
return getCollectionService().getWorkflowGroup(context, this, 2);
}
public Group getWorkflowStep3() {
return workflowStep3;
}
void setWorkflowStep1(Group workflowStep1) {
this.workflowStep1 = workflowStep1;
setModified();
}
void setWorkflowStep2(Group workflowStep2) {
this.workflowStep2 = workflowStep2;
setModified();
}
void setWorkflowStep3(Group workflowStep3) {
this.workflowStep3 = workflowStep3;
setModified();
// FIXME this should be moved to the collectionService or completely removed, see also
// https://jira.duraspace.org/browse/DS-3041
public Group getWorkflowStep3(Context context) {
return getCollectionService().getWorkflowGroup(context, this, 3);
}
/**
@@ -353,4 +328,10 @@ public class Collection extends DSpaceObject implements DSpaceObjectLegacySuppor
}
return collectionService;
}
@Override
public String getTypeText() {
return Constants.typeText[Constants.COLLECTION];
}
}

View File

@@ -47,6 +47,11 @@ import org.dspace.event.Event;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.harvest.service.HarvestedCollectionService;
import org.dspace.workflow.factory.WorkflowServiceFactory;
import org.dspace.xmlworkflow.WorkflowConfigurationException;
import org.dspace.xmlworkflow.factory.XmlWorkflowFactory;
import org.dspace.xmlworkflow.state.Workflow;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
import org.dspace.xmlworkflow.storedcomponents.service.CollectionRoleService;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -88,6 +93,11 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl<Collection> i
@Autowired(required = true)
protected HarvestedCollectionService harvestedCollectionService;
@Autowired(required = true)
protected XmlWorkflowFactory workflowFactory;
@Autowired(required = true)
protected CollectionRoleService collectionRoleService;
protected CollectionServiceImpl() {
super();
@@ -340,91 +350,95 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl<Collection> i
// Check authorisation - Must be an Admin to create Workflow Group
AuthorizeUtil.authorizeManageWorkflowsGroup(context, collection);
if (getWorkflowGroup(collection, step) == null) {
if (getWorkflowGroup(context, collection, step) == null) {
//turn off authorization so that Collection Admins can create Collection Workflow Groups
context.turnOffAuthorisationSystem();
Group g = groupService.create(context);
context.restoreAuthSystemState();
groupService.setName(g,
"COLLECTION_" + collection.getID() + "_WORKFLOW_STEP_" + step);
groupService.update(context, g);
context.restoreAuthSystemState();
setWorkflowGroup(context, collection, step, g);
}
return getWorkflowGroup(collection, step);
return getWorkflowGroup(context, collection, step);
}
@Override
public void setWorkflowGroup(Context context, Collection collection, int step, Group group)
throws SQLException, AuthorizeException {
// we need to store the old group to be able to revoke permissions if granted before
Group oldGroup = null;
int action;
Workflow workflow = null;
try {
workflow = workflowFactory.getWorkflow(collection);
} catch (IOException | WorkflowConfigurationException e) {
log.error(LogManager.getHeader(context, "setWorkflowGroup",
"collection_id=" + collection.getID() + " " + e.getMessage()), e);
}
if (!StringUtils.equals(XmlWorkflowFactory.LEGACY_WORKFLOW_NAME, workflow.getID())) {
throw new IllegalArgumentException(
"setWorkflowGroup can be used only on collection with the default basic dspace workflow. "
+ "Instead, the collection: "
+ collection.getID() + " has the workflow: " + workflow.getID());
}
String roleId;
switch (step) {
case 1:
oldGroup = collection.getWorkflowStep1();
action = Constants.WORKFLOW_STEP_1;
collection.setWorkflowStep1(group);
roleId = CollectionRoleService.LEGACY_WORKFLOW_STEP1_NAME;
break;
case 2:
oldGroup = collection.getWorkflowStep2();
action = Constants.WORKFLOW_STEP_2;
collection.setWorkflowStep2(group);
roleId = CollectionRoleService.LEGACY_WORKFLOW_STEP2_NAME;
break;
case 3:
oldGroup = collection.getWorkflowStep3();
action = Constants.WORKFLOW_STEP_3;
collection.setWorkflowStep3(group);
roleId = CollectionRoleService.LEGACY_WORKFLOW_STEP3_NAME;
break;
default:
throw new IllegalArgumentException("Illegal step count: " + step);
}
// deal with permissions.
try {
context.turnOffAuthorisationSystem();
// remove the policies for the old group
if (oldGroup != null) {
Iterator<ResourcePolicy> oldPolicies =
resourcePolicyService.find(context, collection, oldGroup, action).iterator();
while (oldPolicies.hasNext()) {
resourcePolicyService.delete(context, oldPolicies.next());
}
oldPolicies = resourcePolicyService.find(context, collection, oldGroup, Constants.ADD).iterator();
while (oldPolicies.hasNext()) {
ResourcePolicy rp = oldPolicies.next();
if (rp.getRpType() == ResourcePolicy.TYPE_WORKFLOW) {
resourcePolicyService.delete(context, rp);
}
}
}
// group can be null to delete workflow step.
// we need to grant permissions if group is not null
CollectionRole colRole = collectionRoleService.find(context, collection, roleId);
if (colRole == null) {
if (group != null) {
authorizeService.addPolicy(context, collection, action, group, ResourcePolicy.TYPE_WORKFLOW);
authorizeService.addPolicy(context, collection, Constants.ADD, group, ResourcePolicy.TYPE_WORKFLOW);
colRole = collectionRoleService.create(context, collection, roleId, group);
}
} else {
if (group != null) {
colRole.setGroup(group);
collectionRoleService.update(context, colRole);
} else {
collectionRoleService.delete(context, colRole);
}
} finally {
context.restoreAuthSystemState();
}
collection.setModified();
}
@Override
public Group getWorkflowGroup(Collection collection, int step) {
public Group getWorkflowGroup(Context context, Collection collection, int step) {
String roleId;
switch (step) {
case 1:
return collection.getWorkflowStep1();
roleId = CollectionRoleService.LEGACY_WORKFLOW_STEP1_NAME;
break;
case 2:
return collection.getWorkflowStep2();
roleId = CollectionRoleService.LEGACY_WORKFLOW_STEP2_NAME;
break;
case 3:
return collection.getWorkflowStep3();
roleId = CollectionRoleService.LEGACY_WORKFLOW_STEP3_NAME;
break;
default:
throw new IllegalStateException("Illegal step count: " + step);
throw new IllegalArgumentException("Illegal step count: " + step);
}
CollectionRole colRole;
try {
colRole = collectionRoleService.find(context, collection, roleId);
if (colRole != null) {
return colRole.getGroup();
}
return null;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@@ -735,29 +749,11 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl<Collection> i
// Remove any Handle
handleService.unbindHandle(context, collection);
// Remove any workflow groups - must happen after deleting collection
Group g = collection.getWorkflowStep1();
if (g != null) {
collection.setWorkflowStep1(null);
groupService.delete(context, g);
}
g = collection.getWorkflowStep2();
if (g != null) {
collection.setWorkflowStep2(null);
groupService.delete(context, g);
}
g = collection.getWorkflowStep3();
if (g != null) {
collection.setWorkflowStep3(null);
groupService.delete(context, g);
}
// Remove any workflow roles
collectionRoleService.deleteByCollection(context, collection);
// Remove default administrators group
g = collection.getAdministrators();
Group g = collection.getAdministrators();
if (g != null) {
collection.setAdmins(null);

View File

@@ -11,6 +11,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -251,6 +252,11 @@ public class Community extends DSpaceObject implements DSpaceObjectLegacySupport
return Constants.COMMUNITY;
}
@Override
public String getTypeText() {
return Constants.typeText[Constants.COMMUNITY];
}
@Override
public String getName() {
String value = getCommunityService()
@@ -269,4 +275,5 @@ public class Community extends DSpaceObject implements DSpaceObjectLegacySupport
}
return communityService;
}
}

View File

@@ -26,6 +26,7 @@ import javax.persistence.Transient;
import org.apache.commons.collections4.CollectionUtils;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.browse.BrowsableObject;
import org.dspace.core.ReloadableEntity;
import org.dspace.handle.Handle;
import org.hibernate.annotations.GenericGenerator;
@@ -36,7 +37,8 @@ import org.hibernate.annotations.GenericGenerator;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "dspaceobject")
public abstract class DSpaceObject implements Serializable, ReloadableEntity<java.util.UUID> {
public abstract class DSpaceObject implements Serializable, ReloadableEntity<java.util.UUID>,
BrowsableObject<UUID> {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")

View File

@@ -146,7 +146,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
public List<MetadataValue> getMetadataByMetadataString(T dso, String mdString) {
StringTokenizer dcf = new StringTokenizer(mdString, ".");
String[] tokens = {"", "", ""};
String[] tokens = { "", "", "" };
int i = 0;
while (dcf.hasMoreTokens()) {
tokens[i] = dcf.nextToken().trim();
@@ -236,7 +236,8 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
@Override
public void addMetadata(Context context, T dso, MetadataField metadataField, String lang, List<String> values,
List<String> authorities, List<Integer> confidences) throws SQLException {
List<String> authorities, List<Integer> confidences)
throws SQLException {
boolean authorityControlled = metadataAuthorityService.isAuthorityControlled(metadataField);
boolean authorityRequired = metadataAuthorityService.isAuthorityRequired(metadataField);
// We will not verify that they are valid entries in the registry
@@ -532,7 +533,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
protected String[] getMDValueByField(String field) {
StringTokenizer dcf = new StringTokenizer(field, ".");
String[] tokens = {"", "", ""};
String[] tokens = { "", "", "" };
int i = 0;
while (dcf.hasMoreTokens()) {
tokens[i] = dcf.nextToken().trim();
@@ -752,4 +753,5 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
idx++;
}
}
}

View File

@@ -7,8 +7,10 @@
*/
package org.dspace.content;
import java.io.Serializable;
import java.sql.SQLException;
import org.dspace.browse.BrowsableObject;
import org.dspace.eperson.EPerson;
/**
@@ -18,13 +20,13 @@ import org.dspace.eperson.EPerson;
* @author Robert Tansley
* @version $Revision$
*/
public interface InProgressSubmission {
public interface InProgressSubmission<ID extends Serializable> extends BrowsableObject<ID> {
/**
* Get the internal ID of this submission
*
* @return the internal identifier
*/
Integer getID();
ID getID();
/**
* Get the incomplete item object

View File

@@ -13,6 +13,7 @@ import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -27,6 +28,7 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import org.apache.log4j.Logger;
import org.dspace.content.comparator.NameAscendingComparator;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService;
@@ -52,6 +54,12 @@ import org.hibernate.proxy.HibernateProxyHelper;
@Entity
@Table(name = "item")
public class Item extends DSpaceObject implements DSpaceObjectLegacySupport {
/**
* log4j logger
*/
private static Logger log = Logger.getLogger(Item.class);
/**
* Wild card for Dublin Core metadata qualifiers/languages
*/
@@ -366,4 +374,10 @@ public class Item extends DSpaceObject implements DSpaceObjectLegacySupport {
}
return itemService;
}
@Override
public String getTypeText() {
return getItemService().getTypeText(this);
}
}

View File

@@ -33,6 +33,7 @@ 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.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BundleService;
@@ -58,6 +59,7 @@ import org.dspace.identifier.service.IdentifierService;
import org.dspace.services.ConfigurationService;
import org.dspace.versioning.service.VersioningService;
import org.dspace.workflow.WorkflowItemService;
import org.dspace.workflow.factory.WorkflowServiceFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -1123,6 +1125,16 @@ prevent the generation of resource policy entry values with null dspace_object a
if (ownCollection != null) {
return ownCollection;
} else {
InProgressSubmission inprogress = ContentServiceFactory.getInstance().getWorkspaceItemService()
.findByItem(context,
item);
if (inprogress == null) {
inprogress = WorkflowServiceFactory.getInstance().getWorkflowItemService().findByItem(context, item);
}
if (inprogress != null) {
return inprogress.getCollection();
}
// is a template item?
return item.getTemplateItemOf();
}
@@ -1251,6 +1263,12 @@ prevent the generation of resource policy entry values with null dspace_object a
return itemDAO.countItems(context, false, false);
}
@Override
public int countArchivedItems(Context context) throws SQLException {
// return count of items in archive and also not withdrawn
return itemDAO.countItems(context, true, false);
}
@Override
public int countWithdrawnItems(Context context) throws SQLException {
// return count of items that are not in archive and withdrawn
@@ -1342,6 +1360,7 @@ prevent the generation of resource policy entry values with null dspace_object a
List<MetadataValue> fullMetadataValueList = new LinkedList<>();
if (enableVirtualMetadata) {
fullMetadataValueList.addAll(getRelationshipMetadata(item, true));
}
fullMetadataValueList.addAll(dbMetadataValues);

View File

@@ -11,6 +11,7 @@ import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -26,6 +27,8 @@ import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.dspace.browse.BrowsableObject;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.ReloadableEntity;
import org.dspace.eperson.EPerson;
@@ -41,7 +44,8 @@ import org.hibernate.proxy.HibernateProxyHelper;
*/
@Entity
@Table(name = "workspaceitem")
public class WorkspaceItem implements InProgressSubmission, Serializable, ReloadableEntity<Integer> {
public class WorkspaceItem
implements InProgressSubmission<Integer>, Serializable, ReloadableEntity<Integer>, BrowsableObject<Integer> {
@Id
@Column(name = "workspace_item_id", unique = true, nullable = false)
@@ -238,4 +242,10 @@ public class WorkspaceItem implements InProgressSubmission, Serializable, Reload
void addSupervisorGroup(Group group) {
supervisorGroups.add(group);
}
@Override
public int getType() {
return Constants.WORKSPACEITEM;
}
}

View File

@@ -27,6 +27,7 @@ import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
import org.dspace.event.Event;
import org.dspace.workflow.WorkflowItem;
import org.dspace.workflow.WorkflowService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -60,7 +61,12 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
}
@Override
public WorkspaceItem find(Context context, int id) throws SQLException {
public int getSupportsTypeConstant() {
return Constants.WORKSPACEITEM;
}
@Override
public WorkspaceItem find(Context context, Integer id) throws SQLException {
WorkspaceItem workspaceItem = workspaceItemDAO.findByID(context, WorkspaceItem.class, id);
if (workspaceItem == null) {
@@ -130,6 +136,9 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
+ "item_id=" + item.getID() + "collection_id="
+ collection.getID()));
context.addEvent(new Event(Event.MODIFY, Constants.ITEM, item.getID(), null,
itemService.getIdentifiers(context, item)));
return workspaceItem;
}

View File

@@ -35,6 +35,13 @@ public interface CollectionDAO extends DSpaceObjectLegacySupportDAO<Collection>
public Collection findByTemplateItem(Context context, Item item) throws SQLException;
/**
*
* @param context DSpace Context
* @param group EPerson Group
* @return the collection, if any, that has the specified group as administrators or submitters
* @throws SQLException
*/
public Collection findByGroup(Context context, Group group) throws SQLException;
public List<Collection> findAuthorized(Context context, EPerson ePerson, List<Integer> actions) throws SQLException;

View File

@@ -14,6 +14,7 @@ import java.util.List;
import java.util.UUID;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.core.Context;
@@ -131,4 +132,17 @@ public interface ItemDAO extends DSpaceObjectLegacySupportDAO<Item> {
*/
int countItems(Context context, boolean includeArchived, boolean includeWithdrawn) throws SQLException;
/**
* Count number of items from the specified submitter based on specific status flags
*
* @param context context
* @param submitter the submitter
* @param includeArchived whether to include archived items in count
* @param includeWithdrawn whether to include withdrawn items in count
* @return count of items
* @throws SQLException if database error
*/
public int countItems(Context context, EPerson submitter, boolean includeArchived, boolean includeWithdrawn)
throws SQLException;
}

View File

@@ -97,10 +97,7 @@ public class CollectionDAOImpl extends AbstractHibernateDSODAO<Collection> imple
Root<Collection> collectionRoot = criteriaQuery.from(Collection.class);
criteriaQuery.select(collectionRoot);
criteriaQuery
.where(criteriaBuilder.or(criteriaBuilder.equal(collectionRoot.get(Collection_.workflowStep1), group),
criteriaBuilder.equal(collectionRoot.get(Collection_.workflowStep2), group),
criteriaBuilder.equal(collectionRoot.get(Collection_.workflowStep3), group),
criteriaBuilder.equal(collectionRoot.get(Collection_.submitters), group),
.where(criteriaBuilder.or(criteriaBuilder.equal(collectionRoot.get(Collection_.submitters), group),
criteriaBuilder.equal(collectionRoot.get(Collection_.admins), group)
)
);

View File

@@ -126,8 +126,8 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
@Override
public Iterator<Item> findByMetadataField(Context context, MetadataField metadataField, String value,
boolean inArchive) throws SQLException {
String hqlQueryString = "SELECT item FROM Item as item join item.metadata metadatavalue WHERE item" +
".inArchive=:in_archive AND metadatavalue.metadataField = :metadata_field";
String hqlQueryString = "SELECT item FROM Item as item join item.metadata metadatavalue " +
"WHERE item.inArchive=:in_archive AND metadatavalue.metadataField = :metadata_field";
if (value != null) {
hqlQueryString += " AND STR(metadatavalue.value) = :text_value";
}
@@ -257,8 +257,8 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
public Iterator<Item> findByAuthorityValue(Context context, MetadataField metadataField, String authority,
boolean inArchive) throws SQLException {
Query query = createQuery(context,
"SELECT item FROM Item as item join item.metadata metadatavalue WHERE item" +
".inArchive=:in_archive AND metadatavalue.metadataField = :metadata_field AND " +
"SELECT item FROM Item as item join item.metadata metadatavalue " +
"WHERE item.inArchive=:in_archive AND metadatavalue.metadataField = :metadata_field AND " +
"metadatavalue.authority = :authority");
query.setParameter("in_archive", inArchive);
query.setParameter("metadata_field", metadataField);
@@ -270,8 +270,8 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
public Iterator<Item> findArchivedByCollection(Context context, Collection collection, Integer limit,
Integer offset) throws SQLException {
Query query = createQuery(context,
"select i from Item i join i.collections c WHERE :collection IN c AND i" +
".inArchive=:in_archive");
"select i from Item i join i.collections c " +
"WHERE :collection IN c AND i.inArchive=:in_archive");
query.setParameter("collection", collection);
query.setParameter("in_archive", true);
if (offset != null) {
@@ -311,8 +311,8 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
public int countItems(Context context, Collection collection, boolean includeArchived, boolean includeWithdrawn)
throws SQLException {
Query query = createQuery(context,
"select count(i) from Item i join i.collections c WHERE :collection IN c AND i" +
".inArchive=:in_archive AND i.withdrawn=:withdrawn");
"select count(i) from Item i join i.collections c " +
"WHERE :collection IN c AND i.inArchive=:in_archive AND i.withdrawn=:withdrawn");
query.setParameter("collection", collection);
query.setParameter("in_archive", includeArchived);
query.setParameter("withdrawn", includeWithdrawn);
@@ -352,10 +352,23 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
@Override
public int countItems(Context context, boolean includeArchived, boolean includeWithdrawn) throws SQLException {
Query query = createQuery(context,
"SELECT count(*) FROM Item i WHERE i.inArchive=:in_archive AND i" +
".withdrawn=:withdrawn");
"SELECT count(*) FROM Item i " +
"WHERE i.inArchive=:in_archive AND i.withdrawn=:withdrawn");
query.setParameter("in_archive", includeArchived);
query.setParameter("withdrawn", includeWithdrawn);
return count(query);
}
@Override
public int countItems(Context context, EPerson submitter, boolean includeArchived, boolean includeWithdrawn)
throws SQLException {
Query query = createQuery(context,
"SELECT count(*) FROM Item i join i.submitter submitter " +
"WHERE i.inArchive=:in_archive AND i.withdrawn=:withdrawn AND submitter = :submitter");
query.setParameter("submitter", submitter);
query.setParameter("in_archive", includeArchived);
query.setParameter("withdrawn", includeWithdrawn);
return count(query);
}
}

View File

@@ -7,13 +7,16 @@
*/
package org.dspace.content.factory;
import java.io.Serializable;
import java.util.List;
import org.dspace.browse.BrowsableObject;
import org.dspace.content.DSpaceObject;
import org.dspace.content.InProgressSubmission;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BrowsableObjectService;
import org.dspace.content.service.BundleService;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
@@ -43,6 +46,8 @@ import org.dspace.workflow.factory.WorkflowServiceFactory;
*/
public abstract class ContentServiceFactory {
public abstract List<BrowsableObjectService> getBrowsableDSpaceObjectServices();
public abstract List<DSpaceObjectService<? extends DSpaceObject>> getDSpaceObjectServices();
public abstract List<DSpaceObjectLegacySupportService<? extends DSpaceObject>>
@@ -98,16 +103,29 @@ public abstract class ContentServiceFactory {
return manager;
}
public DSpaceObjectService getDSpaceObjectService(int type) {
@SuppressWarnings("unchecked")
public <T extends DSpaceObject> DSpaceObjectService<T> getDSpaceObjectService(int type) {
for (int i = 0; i < getDSpaceObjectServices().size(); i++) {
DSpaceObjectService objectService = getDSpaceObjectServices().get(i);
DSpaceObjectService<? extends DSpaceObject> objectService = getDSpaceObjectServices().get(i);
if (objectService.getSupportsTypeConstant() == type) {
return objectService;
return (DSpaceObjectService<T>) objectService;
}
}
throw new UnsupportedOperationException("Unknown DSpace type: " + type);
}
@SuppressWarnings("unchecked")
public <T extends BrowsableObject<PK>, PK extends Serializable> BrowsableObjectService<T, PK>
getBrowsableDSpaceObjectService(int type) {
for (int i = 0; i < getBrowsableDSpaceObjectServices().size(); i++) {
BrowsableObjectService objectService = getBrowsableDSpaceObjectServices().get(i);
if (objectService.getSupportsTypeConstant() == type) {
return (BrowsableObjectService<T, PK>) objectService;
}
}
throw new UnsupportedOperationException("Unknown Browsable DSpace type: " + type);
}
public DSpaceObjectLegacySupportService<? extends DSpaceObject> getDSpaceLegacyObjectService(int type) {
for (int i = 0; i < getDSpaceObjectLegacySupportServices().size(); i++) {
DSpaceObjectLegacySupportService<? extends DSpaceObject> objectLegacySupportService =

View File

@@ -12,6 +12,7 @@ import java.util.List;
import org.dspace.content.DSpaceObject;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BrowsableObjectService;
import org.dspace.content.service.BundleService;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
@@ -29,6 +30,7 @@ import org.dspace.content.service.RelationshipTypeService;
import org.dspace.content.service.SiteService;
import org.dspace.content.service.SupervisedItemService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.utils.DSpace;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -39,7 +41,6 @@ import org.springframework.beans.factory.annotation.Autowired;
*/
public class ContentServiceFactoryImpl extends ContentServiceFactory {
@Autowired(required = true)
private List<DSpaceObjectService<? extends DSpaceObject>> dSpaceObjectServices;
@Autowired(required = true)
@@ -81,6 +82,11 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory {
@Autowired(required = true)
private EntityService entityService;
@Override
public List<BrowsableObjectService> getBrowsableDSpaceObjectServices() {
return new DSpace().getServiceManager().getServicesByType(BrowsableObjectService.class);
}
@Override
public List<DSpaceObjectService<? extends DSpaceObject>> getDSpaceObjectServices() {
return dSpaceObjectServices;
@@ -175,4 +181,5 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory {
public EntityService getEntityService() {
return entityService;
}
}

View File

@@ -299,7 +299,7 @@ public class RoleDisseminator implements PackageDisseminator {
writer.writeAttribute(ID, String.valueOf(group.getID()));
writer.writeAttribute(NAME, exportGroupName);
String groupType = getGroupType(relatedObject, group);
String groupType = getGroupType(context, relatedObject, group);
if (groupType != null && !groupType.isEmpty()) {
writer.writeAttribute(TYPE, groupType);
}
@@ -349,7 +349,7 @@ public class RoleDisseminator implements PackageDisseminator {
* @param group the group
* @return a group type string or null
*/
protected String getGroupType(DSpaceObject dso, Group group) {
protected String getGroupType(Context context, DSpaceObject dso, Group group) {
if (dso == null || group == null) {
return null;
}
@@ -370,13 +370,13 @@ public class RoleDisseminator implements PackageDisseminator {
} else if (group.equals(collection.getSubmitters())) {
//Check if Submitters group
return GROUP_TYPE_SUBMIT;
} else if (group.equals(collection.getWorkflowStep1())) {
} else if (group.equals(collection.getWorkflowStep1(context))) {
//Check if workflow step 1 group
return GROUP_TYPE_WORKFLOW_STEP_1;
} else if (group.equals(collection.getWorkflowStep2())) {
} else if (group.equals(collection.getWorkflowStep2(context))) {
//check if workflow step 2 group
return GROUP_TYPE_WORKFLOW_STEP_2;
} else if (group.equals(collection.getWorkflowStep3())) {
} else if (group.equals(collection.getWorkflowStep3(context))) {
//check if workflow step 3 group
return GROUP_TYPE_WORKFLOW_STEP_3;
}
@@ -521,16 +521,16 @@ public class RoleDisseminator implements PackageDisseminator {
list.add(collection.getSubmitters());
}
//check for workflow step 1 group
if (collection.getWorkflowStep1() != null) {
list.add(collection.getWorkflowStep1());
if (collection.getWorkflowStep1(context) != null) {
list.add(collection.getWorkflowStep1(context));
}
//check for workflow step 2 group
if (collection.getWorkflowStep2() != null) {
list.add(collection.getWorkflowStep2());
if (collection.getWorkflowStep2(context) != null) {
list.add(collection.getWorkflowStep2(context));
}
//check for workflow step 3 group
if (collection.getWorkflowStep3() != null) {
list.add(collection.getWorkflowStep3());
if (collection.getWorkflowStep3(context) != null) {
list.add(collection.getWorkflowStep3(context));
}
// FINAL CATCH-ALL -> Find any other groups where name begins with "COLLECTION_<ID>_"

View File

@@ -12,6 +12,7 @@ import java.io.InputStream;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
@@ -31,6 +32,8 @@ import org.dspace.core.Context;
*/
public interface BitstreamService extends DSpaceObjectService<Bitstream>, DSpaceObjectLegacySupportService<Bitstream> {
public Bitstream find(Context context, UUID id) throws SQLException;
public List<Bitstream> findAll(Context context) throws SQLException;
public Iterator<Bitstream> findAll(Context context, int limit, int offset) throws SQLException;

View File

@@ -0,0 +1,44 @@
/**
* 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/
*/
package org.dspace.content.service;
import java.io.Serializable;
import java.sql.SQLException;
import org.dspace.browse.BrowsableObject;
import org.dspace.core.Context;
/**
* Service interface class for any BrowsableDSpaceObject.
* All BrowsableObject service classes should implement this class since it offers some basic methods which all
* BrowsableObjects are required to have.
*
* @param <T> class type
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
public interface BrowsableObjectService<T extends BrowsableObject<PK>, PK extends Serializable> {
/**
* Generic find for when the precise type of a BDSO is not known, just the
* a pair of type number and database ID.
*
* @param context - the context
* @param id - id within table of type'd objects
* @return the object found, or null if it does not exist.
* @throws SQLException only upon failure accessing the database.
*/
public T find(Context context, PK id) throws SQLException;
/**
* Returns the Constants which this service supports
*
* @return a org.dspace.core.Constants that represents a BrowsableDSpaceObject type
*/
public int getSupportsTypeConstant();
}

View File

@@ -159,11 +159,12 @@ public interface CollectionService
* This returns <code>null</code> if there is no group associated with
* this collection for the given step.
*
* @param context DSpace Context
* @param collection Collection
* @param step the workflow step (1-3)
* @return the group of reviewers or <code>null</code>
*/
public Group getWorkflowGroup(Collection collection, int step);
public Group getWorkflowGroup(Context context, Collection collection, int step);
/**
* Create a default submitters group if one does not already exist. Returns
@@ -317,6 +318,13 @@ public interface CollectionService
public List<Collection> findAuthorized(Context context, Community community, int actionID)
throws java.sql.SQLException;
/**
*
* @param context DSpace Context
* @param group EPerson Group
* @return the collection, if any, that has the specified group as administrators or submitters
* @throws SQLException
*/
public Collection findByGroup(Context context, Group group) throws SQLException;
List<Collection> findCollectionsWithSubscribers(Context context) throws SQLException;

View File

@@ -28,19 +28,7 @@ import org.dspace.core.Context;
* @param <T> class type
* @author kevinvandevelde at atmire.com
*/
public interface DSpaceObjectService<T extends DSpaceObject> {
/**
* Generic find for when the precise type of a DSO is not known, just the
* a pair of type number and database ID.
*
* @param context - the context
* @param id - id within table of type'd objects
* @return the object found, or null if it does not exist.
* @throws SQLException only upon failure accessing the database.
*/
public T find(Context context, UUID id) throws SQLException;
public interface DSpaceObjectService<T extends DSpaceObject> extends BrowsableObjectService<T, UUID> {
/**
* Get a proper name for the object. This may return <code>null</code>.
@@ -251,6 +239,19 @@ public interface DSpaceObjectService<T extends DSpaceObject> {
public void addMetadata(Context context, T dso, MetadataField metadataField, String lang, List<String> values,
List<String> authorities, List<Integer> confidences) throws SQLException;
/**
* Shortcut for {@link #addMetadata(Context, DSpaceObject, MetadataField, String, List, List, List)} when a single
* value need to be added
*
* @param context
* @param dso
* @param metadataField
* @param language
* @param value
* @param authority
* @param confidence
* @throws SQLException
*/
public void addMetadata(Context context, T dso, MetadataField metadataField, String language, String value,
String authority, int confidence) throws SQLException;
@@ -361,13 +362,6 @@ public interface DSpaceObjectService<T extends DSpaceObject> {
public void delete(Context context, T dso) throws SQLException, AuthorizeException, IOException;
/**
* Returns the Constants which this service supports
*
* @return a org.dspace.core.Constants that represents a DSpaceObjct type
*/
public int getSupportsTypeConstant();
void addAndShiftRightMetadata(Context context, T dso, String schema, String element, String qualifier, String lang,
String value, String authority, int confidence, int index) throws SQLException;

View File

@@ -7,6 +7,7 @@
*/
package org.dspace.content.service;
import java.io.Serializable;
import java.sql.SQLException;
import org.dspace.app.util.DCInputsReaderException;
@@ -24,7 +25,8 @@ import org.dspace.core.Context;
* @param <T> class type
* @author kevinvandevelde at atmire.com
*/
public interface InProgressSubmissionService<T extends InProgressSubmission> {
public interface InProgressSubmissionService<T extends InProgressSubmission<ID>, ID extends Serializable>
extends BrowsableObjectService<T, ID> {
/**
* Deletes submission wrapper, doesn't delete item contents
@@ -48,4 +50,5 @@ public interface InProgressSubmissionService<T extends InProgressSubmission> {
public void move(Context context, T inProgressSubmission, Collection fromCollection, Collection toCollection)
throws DCInputsReaderException;
}

View File

@@ -40,6 +40,7 @@ import org.dspace.eperson.Group;
* @author kevinvandevelde at atmire.com
*/
public interface ItemService extends DSpaceObjectService<Item>, DSpaceObjectLegacySupportService<Item> {
public Thumbnail getThumbnail(Context context, Item item, boolean requireOriginal) throws SQLException;
/**
@@ -619,16 +620,25 @@ public interface ItemService extends DSpaceObjectService<Item>, DSpaceObjectLega
* counts all items not in archive
*
* @param context DSpace context object
* @return total items
* @return total items NOT in archive
* @throws SQLException if database error
*/
int countNotArchivedItems(Context context) throws SQLException;
/**
* counts all items in archive
*
* @param context DSpace context object
* @return total items in archive
* @throws SQLException if database error
*/
int countArchivedItems(Context context) throws SQLException;
/**
* counts all withdrawn items
*
* @param context DSpace context object
* @return total items
* @return total items withdrawn
* @throws SQLException if database error
*/
int countWithdrawnItems(Context context) throws SQLException;
@@ -707,4 +717,5 @@ public interface ItemService extends DSpaceObjectService<Item>, DSpaceObjectLega
public List<MetadataValue> getMetadata(Item item, String schema, String element, String qualifier,
String lang, boolean enableVirtualMetadata);
}

View File

@@ -27,19 +27,7 @@ import org.dspace.workflow.WorkflowItem;
*
* @author kevinvandevelde at atmire.com
*/
public interface WorkspaceItemService extends InProgressSubmissionService<WorkspaceItem> {
/**
* Get a workspace item from the database. The item, collection and
* submitter are loaded into memory.
*
* @param context DSpace context object
* @param id ID of the workspace item
* @return the workspace item, or null if the ID is invalid.
* @throws SQLException if database error
*/
public WorkspaceItem find(Context context, int id) throws SQLException;
public interface WorkspaceItemService extends InProgressSubmissionService<WorkspaceItem, Integer> {
/**
* Create a new workspace item, with a new ID. An Item is also created. The

View File

@@ -12,12 +12,14 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Stream;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Root;
import com.google.common.collect.AbstractIterator;
import org.apache.commons.collections.CollectionUtils;
import org.hibernate.Session;
@@ -269,8 +271,19 @@ public abstract class AbstractHibernateDAO<T> implements GenericDAO<T> {
*/
public Iterator<T> iterate(Query query) {
@SuppressWarnings("unchecked")
Iterator<T> result = (Iterator<T>) query.getResultList().iterator();
return result;
org.hibernate.query.Query hquery = query.unwrap(org.hibernate.query.Query.class);
Stream<T> stream = hquery.stream();
Iterator<T> iter = stream.iterator();
return new AbstractIterator<T> () {
@Override
protected T computeNext() {
return iter.hasNext() ? iter.next() : endOfData();
}
@Override
public void finalize() {
stream.close();
}
};
}
/**

View File

@@ -55,11 +55,31 @@ public class Constants {
*/
public static final int EPERSON = 7;
/**
* Type of workspace item objects
*/
public static final int WORKSPACEITEM = 8;
/**
* Type of workflow item objects
*/
public static final int WORKFLOWITEM = 9;
/**
* Type of pool task objects
*/
public static final int POOLTASK = 10;
/**
* Type of claimed task objects
*/
public static final int CLAIMEDTASK = 11;
/**
* lets you look up type names from the type IDs
*/
public static final String[] typeText = {"BITSTREAM", "BUNDLE", "ITEM",
"COLLECTION", "COMMUNITY", "SITE", "GROUP", "EPERSON"};
public static final String[] typeText = { "BITSTREAM", "BUNDLE", "ITEM", "COLLECTION", "COMMUNITY", "SITE", "GROUP",
"EPERSON", "WORKSPACEITEM", "WORKFLOWITEM", "POOLTASK", "CLAIMEDTASK" };
/**
* Special Bundle and Bitstream Names:
@@ -179,10 +199,10 @@ public class Constants {
/**
* lets you look up action names from the action IDs
*/
public static final String[] actionText = {"READ", "WRITE",
public static final String[] actionText = { "READ", "WRITE",
"OBSOLETE (DELETE)", "ADD", "REMOVE", "WORKFLOW_STEP_1",
"WORKFLOW_STEP_2", "WORKFLOW_STEP_3", "WORKFLOW_ABORT",
"DEFAULT_BITSTREAM_READ", "DEFAULT_ITEM_READ", "ADMIN", "WITHDRAWN_READ"};
"DEFAULT_BITSTREAM_READ", "DEFAULT_ITEM_READ", "ADMIN", "WITHDRAWN_READ" };
/**
* generating constants for the relevance array dynamically is simple: just

View File

@@ -226,7 +226,7 @@ public class WorkflowCuratorServiceImpl implements WorkflowCuratorService {
int step = state2step(wfi.getState());
// make sure this step exists
if (step < 4) {
Group wfGroup = collectionService.getWorkflowGroup(wfi.getCollection(), step);
Group wfGroup = collectionService.getWorkflowGroup(c, wfi.getCollection(), step);
if (wfGroup != null) {
epList.addAll(groupService.allMembers(c, wfGroup));
}

View File

@@ -24,6 +24,7 @@ import org.apache.commons.lang3.tuple.Pair;
import org.dspace.authorize.AuthorizeConfiguration;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject;
import org.dspace.content.DSpaceObjectServiceImpl;
import org.dspace.content.MetadataField;
@@ -39,6 +40,8 @@ import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.GroupService;
import org.dspace.event.Event;
import org.dspace.util.UUIDUtils;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
import org.dspace.xmlworkflow.storedcomponents.service.CollectionRoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -62,6 +65,9 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
@Autowired(required = true)
protected CollectionService collectionService;
@Autowired(required = true)
protected CollectionRoleService collectionRoleService;
@Autowired(required = true)
protected EPersonService ePersonService;
@@ -615,15 +621,6 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
org.dspace.content.Collection collection = collectionService.findByGroup(context, group);
if (collection != null) {
if ((group.equals(collection.getWorkflowStep1()) ||
group.equals(collection.getWorkflowStep2()) ||
group.equals(collection.getWorkflowStep3()))) {
if (AuthorizeConfiguration.canCollectionAdminManageWorkflows()) {
return collection;
} else if (AuthorizeConfiguration.canCommunityAdminManageCollectionWorkflows()) {
return collectionService.getParentObject(context, collection);
}
}
if (group.equals(collection.getSubmitters())) {
if (AuthorizeConfiguration.canCollectionAdminManageSubmitters()) {
return collection;
@@ -638,12 +635,34 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
return collectionService.getParentObject(context, collection);
}
}
} else if (AuthorizeConfiguration.canCommunityAdminManageAdminGroup()) {
} else {
if (AuthorizeConfiguration.canCollectionAdminManageWorkflows()
|| AuthorizeConfiguration.canCommunityAdminManageCollectionWorkflows()) {
// if the group is used for one or more roles on a single collection,
// admins can eventually manage it
List<CollectionRole> collectionRoles = collectionRoleService.findByGroup(context, group);
if (collectionRoles != null && collectionRoles.size() > 0) {
Set<Collection> colls = new HashSet<Collection>();
for (CollectionRole cr : collectionRoles) {
colls.add(cr.getCollection());
}
if (colls.size() == 1) {
collection = colls.iterator().next();
if (AuthorizeConfiguration.canCollectionAdminManageWorkflows()) {
return collection;
} else {
return collectionService.getParentObject(context, collection);
}
}
}
}
if (AuthorizeConfiguration.canCommunityAdminManageAdminGroup()) {
// is the group related to a community and community administrator allowed
// to manage it?
return communityService.findByAdminGroup(context, group);
}
}
}
return null;
}

View File

@@ -0,0 +1,61 @@
/**
* 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/
*/
package org.dspace.storage.rdbms.migration;
import java.sql.Connection;
import org.dspace.core.Constants;
import org.dspace.storage.rdbms.DatabaseUtils;
import org.dspace.workflow.factory.WorkflowServiceFactory;
import org.dspace.xmlworkflow.service.XmlWorkflowService;
import org.flywaydb.core.api.migration.MigrationChecksumProvider;
import org.flywaydb.core.api.migration.jdbc.JdbcMigration;
import org.flywaydb.core.internal.util.scanner.classpath.ClassPathResource;
/**
* This class automatically adding rptype to the resource policy created with a migration into XML-based Configurable
* Workflow system
*
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/
public class V7_0_2018_04_03__Upgrade_Workflow_Policy implements JdbcMigration, MigrationChecksumProvider {
// Size of migration script run
protected Integer migration_file_size = -1;
@Override
public void migrate(Connection connection) throws Exception {
// Make sure XML Workflow is enabled, shouldn't even be needed since this class is only loaded if the service
// is enabled.
if (WorkflowServiceFactory.getInstance().getWorkflowService() instanceof XmlWorkflowService) {
// Now, check if the XMLWorkflow table (cwf_workflowitem) already exists in this database
if (DatabaseUtils.tableExists(connection, "cwf_workflowitem")) {
String dbtype = DatabaseUtils.getDbType(connection);
String sqlMigrationPath = "org/dspace/storage/rdbms/sqlmigration/workflow/" + dbtype + "/";
String dataMigrateSQL = new ClassPathResource(sqlMigrationPath +
"xmlworkflow" +
"/V7.0_2018.04.03__upgrade_workflow_policy.sql",
getClass().getClassLoader())
.loadAsString(Constants.DEFAULT_ENCODING);
// Actually execute the Data migration SQL
// This will migrate all existing traditional workflows to the new XMLWorkflow system & tables
DatabaseUtils.executeSql(connection, dataMigrateSQL);
// Assuming both succeeded, save the size of the scripts for getChecksum() below
migration_file_size = dataMigrateSQL.length();
}
}
}
@Override
public Integer getChecksum() {
return migration_file_size;
}
}

View File

@@ -76,6 +76,8 @@ public class V5_0_2014_11_04__Enable_XMLWorkflow_Migration
dbFileLocation = "postgres";
} else if (dbtype.toLowerCase().contains("oracle")) {
dbFileLocation = "oracle";
} else if (dbtype.toLowerCase().contains("h2")) {
dbFileLocation = "h2";
}

View File

@@ -55,6 +55,8 @@ public class V6_0_2015_09_01__DS_2701_Enable_XMLWorkflow_Migration implements Jd
dbFileLocation = "postgres";
} else if (dbtype.toLowerCase().contains("oracle")) {
dbFileLocation = "oracle";
} else if (dbtype.toLowerCase().contains("h2")) {
dbFileLocation = "h2";
}

View File

@@ -15,6 +15,6 @@ import org.dspace.core.ReloadableEntity;
*
* @author kevinvandevelde at atmire.com
*/
public interface WorkflowItem extends InProgressSubmission, ReloadableEntity<Integer> {
public interface WorkflowItem extends InProgressSubmission<Integer>, ReloadableEntity<Integer> {
public int getState();
}

View File

@@ -26,20 +26,10 @@ import org.dspace.eperson.EPerson;
*
* @author kevinvandevelde at atmire.com
*/
public interface WorkflowItemService<T extends WorkflowItem> extends InProgressSubmissionService<T> {
public interface WorkflowItemService<T extends WorkflowItem> extends InProgressSubmissionService<T, Integer> {
public T create(Context context, Item item, Collection collection) throws SQLException, AuthorizeException;
/**
* Get a workflow item from the database.
*
* @param context The relevant DSpace Context.
* @param id ID of the workflow item
* @return the workflow item, or null if the ID is invalid.
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
public T find(Context context, int id) throws SQLException;
/**
* return all workflowitems
*

View File

@@ -8,6 +8,7 @@
package org.dspace.workflowbasic;
import java.sql.SQLException;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -22,6 +23,7 @@ import javax.persistence.Table;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.workflow.WorkflowItem;
@@ -145,7 +147,7 @@ public class BasicWorkflowItem implements WorkflowItem {
return collection;
}
void setCollection(Collection collection) {
public void setCollection(Collection collection) {
this.collection = collection;
}
@@ -183,4 +185,10 @@ public class BasicWorkflowItem implements WorkflowItem {
public void setPublishedBefore(boolean b) {
this.publishedBefore = b;
}
@Override
public int getType() {
return Constants.WORKFLOWITEM;
}
}

View File

@@ -17,6 +17,7 @@ import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
@@ -52,6 +53,11 @@ public class BasicWorkflowItemServiceImpl implements BasicWorkflowItemService {
}
@Override
public int getSupportsTypeConstant() {
return Constants.WORKFLOWITEM;
}
@Override
public BasicWorkflowItem create(Context context, Item item, Collection collection)
throws SQLException, AuthorizeException {
@@ -67,7 +73,7 @@ public class BasicWorkflowItemServiceImpl implements BasicWorkflowItemService {
}
@Override
public BasicWorkflowItem find(Context context, int id) throws SQLException {
public BasicWorkflowItem find(Context context, Integer id) throws SQLException {
BasicWorkflowItem workflowItem = workflowItemDAO.findByID(context, BasicWorkflowItem.class, id);
if (workflowItem == null) {

View File

@@ -356,7 +356,7 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
// advance(...) will call itself if no workflow step group exists
// so we need to check permissions only if a workflow step group is
// in place.
if (workflowItem.getCollection().getWorkflowStep1() != null && e != null) {
if (workflowItem.getCollection().getWorkflowStep1(context) != null && e != null) {
authorizeService
.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_1, true);
}
@@ -372,7 +372,7 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
// advance(...) will call itself if no workflow step group exists
// so we need to check permissions only if a workflow step group is
// in place.
if (workflowItem.getCollection().getWorkflowStep2() != null && e != null) {
if (workflowItem.getCollection().getWorkflowStep2(context) != null && e != null) {
authorizeService
.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_2, true);
}
@@ -388,7 +388,7 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
// advance(...) will call itself if no workflow step group exists
// so we need to check permissions only if a workflow step group is
// in place.
if (workflowItem.getCollection().getWorkflowStep3() != null && e != null) {
if (workflowItem.getCollection().getWorkflowStep3(context) != null && e != null) {
authorizeService
.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_3, true);
}
@@ -575,8 +575,8 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
// if there is a workflow state group and it contains any members,
// then we have to check permissions first
if ((collectionService.getWorkflowGroup(collection, step) != null)
&& !(groupService.isEmpty(collectionService.getWorkflowGroup(collection, step)))
if ((collectionService.getWorkflowGroup(context, collection, step) != null)
&& !(groupService.isEmpty(collectionService.getWorkflowGroup(context, collection, step)))
&& newowner != null) {
authorizeService.authorizeAction(context, newowner, collection, correspondingAction, true);
}
@@ -655,7 +655,7 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
// any approvers?
// if so, add them to tasklist
// if not, skip to next state
Group workflowStepGroup = collectionService.getWorkflowGroup(collection, step);
Group workflowStepGroup = collectionService.getWorkflowGroup(context, collection, step);
if ((workflowStepGroup != null) && !(groupService.isEmpty(workflowStepGroup))) {
// set new item state
@@ -1196,18 +1196,18 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
public Group getWorkflowRoleGroup(Context context, Collection collection, String roleName, Group roleGroup)
throws SQLException, AuthorizeException {
if ("WF_STEP1".equals(roleName)) {
roleGroup = collection.getWorkflowStep1();
roleGroup = collection.getWorkflowStep1(context);
if (roleGroup == null) {
roleGroup = collectionService.createWorkflowGroup(context, collection, 1);
}
} else if ("WF_STEP2".equals(roleName)) {
roleGroup = collection.getWorkflowStep2();
roleGroup = collection.getWorkflowStep2(context);
if (roleGroup == null) {
roleGroup = collectionService.createWorkflowGroup(context, collection, 2);
}
} else if ("WF_STEP3".equals(roleName)) {
roleGroup = collection.getWorkflowStep3();
roleGroup = collection.getWorkflowStep3(context);
if (roleGroup == null) {
roleGroup = collectionService.createWorkflowGroup(context, collection, 3);
}

View File

@@ -13,6 +13,7 @@ import java.util.Iterator;
import java.util.List;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
@@ -76,7 +77,7 @@ public class WorkflowRequirementsServiceImpl implements WorkflowRequirementsServ
inProgressUserService.update(context, ipu);
//Make sure the user has the necessary rights to update the item after the tasks is removed from the pool
xmlWorkflowService.grantUserAllItemPolicies(context, wfi.getItem(), user);
xmlWorkflowService.grantUserAllItemPolicies(context, wfi.getItem(), user, ResourcePolicy.TYPE_WORKFLOW);
int totalUsers = inProgressUserService.getNumberOfInProgressUsers(context, wfi) + inProgressUserService
.getNumberOfFinishedUsers(context, wfi);

View File

@@ -18,6 +18,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.UUID;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
@@ -34,6 +35,9 @@ import org.dspace.content.Item;
import org.dspace.content.MetadataSchemaEnum;
import org.dspace.content.MetadataValue;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BundleService;
import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.WorkspaceItemService;
@@ -46,6 +50,7 @@ import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
import org.dspace.event.Event;
import org.dspace.handle.service.HandleService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.usage.UsageWorkflowEvent;
@@ -112,6 +117,12 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
protected XmlWorkflowItemService xmlWorkflowItemService;
@Autowired(required = true)
protected GroupService groupService;
@Autowired(required = true)
protected BundleService bundleService;
@Autowired(required = true)
protected BitstreamFormatService bitstreamFormatService;
@Autowired(required = true)
protected BitstreamService bitstreamService;
protected XmlWorkflowServiceImpl() {
@@ -208,6 +219,8 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
// remove the WorkspaceItem
workspaceItemService.deleteWrapper(context, wsi);
context.restoreAuthSystemState();
context.addEvent(new Event(Event.MODIFY, Constants.ITEM, wfi.getItem().getID(), null,
itemService.getIdentifiers(context, wfi.getItem())));
return wfi;
} catch (WorkflowConfigurationException e) {
throw new WorkflowException(e);
@@ -302,6 +315,13 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
Step currentStep = currentActionConfig.getStep();
if (currentActionConfig.getProcessingAction().isAuthorized(c, request, wi)) {
ActionResult outcome = currentActionConfig.getProcessingAction().execute(c, wi, currentStep, request);
// the cancel action is the default when the request is not understood or a "back to mydspace" was
// pressed in the old UI
if (outcome.getType() == ActionResult.TYPE.TYPE_CANCEL) {
throw new WorkflowException("Unprocessable request for the action " + currentStep.getId());
}
c.addEvent(new Event(Event.MODIFY, Constants.ITEM, wi.getItem().getID(), null,
itemService.getIdentifiers(c, wi.getItem())));
return processOutcome(c, user, workflow, currentStep, currentActionConfig, outcome, wi, false);
} else {
throw new AuthorizeException("You are not allowed to to perform this task.");
@@ -653,6 +673,8 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
removeUserItemPolicies(c, wi.getItem(), task.getOwner());
claimedTaskService.delete(c, task);
}
c.addEvent(new Event(Event.MODIFY, Constants.ITEM, wi.getItem().getID(), null,
itemService.getIdentifiers(c, wi.getItem())));
}
/*
@@ -672,7 +694,7 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
task.setWorkflowItem(wi);
poolTaskService.update(context, task);
//Make sure this user has a task
grantUserAllItemPolicies(context, wi.getItem(), anEpa);
grantUserAllItemPolicies(context, wi.getItem(), anEpa, ResourcePolicy.TYPE_WORKFLOW);
}
for (Group group : assignees.getGroups()) {
PoolTask task = poolTaskService.create(context);
@@ -683,7 +705,7 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
task.setWorkflowItem(wi);
poolTaskService.update(context, task);
//Make sure this user has a task
grantGroupAllItemPolicies(context, wi.getItem(), group);
grantGroupAllItemPolicies(context, wi.getItem(), group, ResourcePolicy.TYPE_WORKFLOW);
}
}
@@ -701,10 +723,10 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
task.setWorkflowID(step.getWorkflow().getID());
claimedTaskService.update(context, task);
//Make sure this user has a task
grantUserAllItemPolicies(context, wi.getItem(), e);
grantUserAllItemPolicies(context, wi.getItem(), e, ResourcePolicy.TYPE_WORKFLOW);
}
public void grantUserAllItemPolicies(Context context, Item item, EPerson epa)
public void grantUserAllItemPolicies(Context context, Item item, EPerson epa, String policyType)
throws AuthorizeException, SQLException {
if (epa != null) {
//A list of policies the user has for this item
@@ -719,24 +741,24 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
//Make sure we don't add duplicate policies
if (!userHasPolicies.contains(Constants.READ)) {
addPolicyToItem(context, item, Constants.READ, epa);
addPolicyToItem(context, item, Constants.READ, epa, policyType);
}
if (!userHasPolicies.contains(Constants.WRITE)) {
addPolicyToItem(context, item, Constants.WRITE, epa);
addPolicyToItem(context, item, Constants.WRITE, epa, policyType);
}
if (!userHasPolicies.contains(Constants.DELETE)) {
addPolicyToItem(context, item, Constants.DELETE, epa);
addPolicyToItem(context, item, Constants.DELETE, epa, policyType);
}
if (!userHasPolicies.contains(Constants.ADD)) {
addPolicyToItem(context, item, Constants.ADD, epa);
addPolicyToItem(context, item, Constants.ADD, epa, policyType);
}
if (!userHasPolicies.contains(Constants.REMOVE)) {
addPolicyToItem(context, item, Constants.REMOVE, epa);
addPolicyToItem(context, item, Constants.REMOVE, epa, policyType);
}
}
}
protected void grantGroupAllItemPolicies(Context context, Item item, Group group)
protected void grantGroupAllItemPolicies(Context context, Item item, Group group, String policyType)
throws AuthorizeException, SQLException {
if (group != null) {
//A list of policies the user has for this item
@@ -750,53 +772,48 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
}
//Make sure we don't add duplicate policies
if (!groupHasPolicies.contains(Constants.READ)) {
addGroupPolicyToItem(context, item, Constants.READ, group);
addGroupPolicyToItem(context, item, Constants.READ, group, policyType);
}
if (!groupHasPolicies.contains(Constants.WRITE)) {
addGroupPolicyToItem(context, item, Constants.WRITE, group);
addGroupPolicyToItem(context, item, Constants.WRITE, group, policyType);
}
if (!groupHasPolicies.contains(Constants.DELETE)) {
addGroupPolicyToItem(context, item, Constants.DELETE, group);
addGroupPolicyToItem(context, item, Constants.DELETE, group, policyType);
}
if (!groupHasPolicies.contains(Constants.ADD)) {
addGroupPolicyToItem(context, item, Constants.ADD, group);
addGroupPolicyToItem(context, item, Constants.ADD, group, policyType);
}
if (!groupHasPolicies.contains(Constants.REMOVE)) {
addGroupPolicyToItem(context, item, Constants.REMOVE, group);
addGroupPolicyToItem(context, item, Constants.REMOVE, group, policyType);
}
}
}
protected void addPolicyToItem(Context context, Item item, int type, EPerson epa)
throws AuthorizeException, SQLException {
addPolicyToItem(context, item, type, epa, null);
}
protected void addPolicyToItem(Context context, Item item, int type, EPerson epa, String policyType)
protected void addPolicyToItem(Context context, Item item, int action, EPerson epa, String policyType)
throws AuthorizeException, SQLException {
if (epa != null) {
authorizeService.addPolicy(context, item, type, epa, policyType);
authorizeService.addPolicy(context, item, action, epa, policyType);
List<Bundle> bundles = item.getBundles();
for (Bundle bundle : bundles) {
authorizeService.addPolicy(context, bundle, type, epa, policyType);
authorizeService.addPolicy(context, bundle, action, epa, policyType);
List<Bitstream> bits = bundle.getBitstreams();
for (Bitstream bit : bits) {
authorizeService.addPolicy(context, bit, type, epa, policyType);
authorizeService.addPolicy(context, bit, action, epa, policyType);
}
}
}
}
protected void addGroupPolicyToItem(Context context, Item item, int type, Group group)
protected void addGroupPolicyToItem(Context context, Item item, int action, Group group, String policyType)
throws AuthorizeException, SQLException {
if (group != null) {
authorizeService.addPolicy(context, item, type, group);
authorizeService.addPolicy(context, item, action, group, policyType);
List<Bundle> bundles = item.getBundles();
for (Bundle bundle : bundles) {
authorizeService.addPolicy(context, bundle, type, group);
authorizeService.addPolicy(context, bundle, action, group, policyType);
List<Bitstream> bits = bundle.getBitstreams();
for (Bitstream bit : bits) {
authorizeService.addPolicy(context, bit, type, group);
authorizeService.addPolicy(context, bit, action, group, policyType);
}
}
}
@@ -886,6 +903,9 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
// convert into personal workspace
WorkspaceItem wsi = returnToWorkspace(context, wi);
// remove policy for controller
removeUserItemPolicies(context, myitem, e);
revokeReviewerPolicies(context, myitem);
// notify that it's been rejected
notifyOfReject(context, wi, e, rejection_message);
log.info(LogManager.getHeader(context, "reject_workflow", "workflow_item_id="
@@ -917,6 +937,8 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
+ "collection_id=" + wi.getCollection().getID() + "eperson_id="
+ e.getID()));
c.addEvent(new Event(Event.MODIFY, Constants.ITEM, wsi.getItem().getID(), null,
itemService.getIdentifiers(c, wsi.getItem())));
c.restoreAuthSystemState();
return wsi;
@@ -948,7 +970,7 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
Item myitem = wfi.getItem();
//Restore permissions for the submitter
grantUserAllItemPolicies(c, myitem, myitem.getSubmitter());
grantUserAllItemPolicies(c, myitem, myitem.getSubmitter(), ResourcePolicy.TYPE_SUBMISSION);
// FIXME: How should this interact with the workflow system?
// FIXME: Remove license
@@ -1043,4 +1065,20 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
public String getMyDSpaceLink() {
return ConfigurationManager.getProperty("dspace.url") + "/mydspace";
}
protected void revokeReviewerPolicies(Context context, Item item) throws SQLException, AuthorizeException {
List<Bundle> bundles = item.getBundles();
for (Bundle originalBundle : bundles) {
// remove bitstream and bundle level policies
for (Bitstream bitstream : originalBundle.getBitstreams()) {
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_WORKFLOW);
}
authorizeService.removeAllPoliciesByDSOAndType(context, originalBundle, ResourcePolicy.TYPE_WORKFLOW);
}
// remove item level policies
authorizeService.removeAllPoliciesByDSOAndType(context, item, ResourcePolicy.TYPE_WORKFLOW);
}
}

View File

@@ -28,6 +28,8 @@ import org.dspace.xmlworkflow.state.actions.WorkflowActionConfig;
*/
public interface XmlWorkflowFactory {
public final String LEGACY_WORKFLOW_NAME = "default";
public Workflow getWorkflow(Collection collection) throws IOException, WorkflowConfigurationException, SQLException;
public Step createStep(Workflow workflow, String stepID) throws WorkflowConfigurationException, IOException;

View File

@@ -70,7 +70,7 @@ public interface XmlWorkflowService extends WorkflowService<XmlWorkflowItem> {
public void createOwnedTask(Context context, XmlWorkflowItem wi, Step step, WorkflowActionConfig action, EPerson e)
throws SQLException, AuthorizeException;
public void grantUserAllItemPolicies(Context context, Item item, EPerson epa)
public void grantUserAllItemPolicies(Context context, Item item, EPerson epa, String actionType)
throws AuthorizeException, SQLException;
public void removeUserItemPolicies(Context context, Item item, EPerson e) throws SQLException, AuthorizeException;

View File

@@ -24,10 +24,6 @@ public class WorkflowActionConfig {
private Step step;
private boolean requiresUI;
private ActionInterface actionUI;
public WorkflowActionConfig(String id) {
this.id = id;
}
@@ -63,11 +59,4 @@ public class WorkflowActionConfig {
return step;
}
public ActionInterface getActionUI() {
return actionUI;
}
public void setActionUI(ActionInterface actionUI) {
this.actionUI = actionUI;
}
}

View File

@@ -11,7 +11,6 @@ import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import org.dspace.app.util.Util;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DCDate;
import org.dspace.content.MetadataSchemaEnum;
@@ -45,59 +44,39 @@ public class AcceptEditRejectAction extends ProcessingAction {
@Override
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
int page = Util.getIntParameter(request, "page");
switch (page) {
case MAIN_PAGE:
return processMainPage(c, wfi, step, request);
case REJECT_PAGE:
if (request.getParameter("submit_approve") != null) {
return processAccept(c, wfi, step, request);
} else {
if (request.getParameter("submit_reject") != null) {
return processRejectPage(c, wfi, step, request);
default:
}
}
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
}
}
public ActionResult processMainPage(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
public ActionResult processAccept(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
throws SQLException, AuthorizeException {
if (request.getParameter("submit_approve") != null) {
//Delete the tasks
addApprovedProvenance(c, wfi);
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
} else if (request.getParameter("submit_reject") != null) {
// Make sure we indicate which page we want to process
request.setAttribute("page", REJECT_PAGE);
// We have pressed reject item, so take the user to a page where he can reject
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
} else {
//We pressed the leave button so return to our submissions page
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
}
}
public ActionResult processRejectPage(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
if (request.getParameter("submit_reject") != null) {
String reason = request.getParameter("reason");
if (reason == null || 0 == reason.trim().length()) {
addErrorField(request, "reason");
request.setAttribute("page", REJECT_PAGE);
return new ActionResult(ActionResult.TYPE.TYPE_ERROR);
}
//We have pressed reject, so remove the task the user has & put it back to a workspace item
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
.sendWorkflowItemBackSubmission(c, wfi, c.getCurrentUser(),
this.getProvenanceStartId(), reason);
// We have pressed reject, so remove the task the user has & put it back
// to a workspace item
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService().sendWorkflowItemBackSubmission(c, wfi,
c.getCurrentUser(), this.getProvenanceStartId(), reason);
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
} else {
//Cancel, go back to the main task page
request.setAttribute("page", MAIN_PAGE);
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
}
}
private void addApprovedProvenance(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {

View File

@@ -9,9 +9,9 @@ package org.dspace.xmlworkflow.state.actions.processingaction;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import org.dspace.app.util.Util;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DCDate;
import org.dspace.content.MetadataSchemaEnum;
@@ -43,34 +43,23 @@ public class ReviewAction extends ProcessingAction {
@Override
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
int page = Util.getIntParameter(request, "page");
switch (page) {
case MAIN_PAGE:
return processMainPage(c, wfi, step, request);
case REJECT_PAGE:
if (request.getParameter("submit_approve") != null) {
return processAccept(c, wfi, step, request);
} else {
if (request.getParameter("submit_reject") != null) {
return processRejectPage(c, wfi, step, request);
default:
}
}
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
}
}
public ActionResult processMainPage(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
public ActionResult processAccept(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
throws SQLException, AuthorizeException {
if (request.getParameter("submit_approve") != null) {
//Delete the tasks
addApprovedProvenance(c, wfi);
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
} else if (request.getParameter("submit_reject") != null) {
// Make sure we indicate which page we want to process
request.setAttribute("page", REJECT_PAGE);
// We have pressed reject item, so take the user to a page where he can reject
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
} else {
//We pressed the leave button so return to our submissions page
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
}
}
private void addApprovedProvenance(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
@@ -92,7 +81,6 @@ public class ReviewAction extends ProcessingAction {
public ActionResult processRejectPage(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
if (request.getParameter("submit_reject") != null) {
String reason = request.getParameter("reason");
if (reason == null || 0 == reason.trim().length()) {
request.setAttribute("page", REJECT_PAGE);
@@ -107,11 +95,5 @@ public class ReviewAction extends ProcessingAction {
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
} else {
//Cancel, go back to the main task page
request.setAttribute("page", MAIN_PAGE);
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
}
}
}

View File

@@ -61,16 +61,10 @@ public class ClaimAction extends UserSelectionAction {
@Override
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
//Check if we are accept this task, or accepting multiple tasks
if (request.getParameter("submit_take_task") != null || request.getParameter("submit_take_tasks") != null) {
//Add a claimed user to our task
XmlWorkflowServiceFactory.getInstance().getWorkflowRequirementsService()
.addClaimedUser(c, wfi, step, c.getCurrentUser());
// accept task, or accepting multiple tasks
XmlWorkflowServiceFactory.getInstance().getWorkflowRequirementsService().addClaimedUser(c, wfi, step,
c.getCurrentUser());
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
} else {
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
}
}
@Override

View File

@@ -18,6 +18,8 @@ import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.dspace.browse.BrowsableObject;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.ReloadableEntity;
import org.dspace.eperson.EPerson;
@@ -32,8 +34,7 @@ import org.dspace.eperson.EPerson;
*/
@Entity
@Table(name = "cwf_claimtask")
public class ClaimedTask implements ReloadableEntity<Integer> {
public class ClaimedTask implements ReloadableEntity<Integer>, BrowsableObject<Integer> {
@Id
@Column(name = "claimtask_id")
@@ -115,4 +116,10 @@ public class ClaimedTask implements ReloadableEntity<Integer> {
public String getWorkflowID() {
return workflowId;
}
@Override
public int getType() {
return Constants.CLAIMEDTASK;
}
}

View File

@@ -14,6 +14,7 @@ import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.xmlworkflow.storedcomponents.dao.ClaimedTaskDAO;
@@ -36,6 +37,11 @@ public class ClaimedTaskServiceImpl implements ClaimedTaskService {
}
@Override
public int getSupportsTypeConstant() {
return Constants.CLAIMEDTASK;
}
@Override
public ClaimedTask create(Context context) throws SQLException, AuthorizeException {
return claimedTaskDAO.create(context, new ClaimedTask());
@@ -46,6 +52,14 @@ public class ClaimedTaskServiceImpl implements ClaimedTaskService {
return claimedTaskDAO.findByID(context, ClaimedTask.class, id);
}
@Override
public ClaimedTask find(Context context, Integer id) throws SQLException {
if (id == null) {
return null;
}
return find(context, id.intValue());
}
@Override
public void update(Context context, ClaimedTask claimedTask) throws SQLException, AuthorizeException {
update(context, Collections.singletonList(claimedTask));

View File

@@ -49,6 +49,11 @@ public class CollectionRoleServiceImpl implements CollectionRoleService {
return collectionRoleDAO.findByCollection(context, collection);
}
@Override
public List<CollectionRole> findByGroup(Context context, Group group) throws SQLException {
return collectionRoleDAO.findByGroup(context, group);
}
@Override
public CollectionRole create(Context context, Collection collection, String roleId, Group group)
throws SQLException {

View File

@@ -7,7 +7,6 @@
*/
package org.dspace.xmlworkflow.storedcomponents;
import java.sql.SQLException;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -20,6 +19,8 @@ import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.dspace.browse.BrowsableObject;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.ReloadableEntity;
import org.dspace.eperson.EPerson;
@@ -35,7 +36,7 @@ import org.dspace.eperson.Group;
*/
@Entity
@Table(name = "cwf_pooltask")
public class PoolTask implements ReloadableEntity<Integer> {
public class PoolTask implements ReloadableEntity<Integer>, BrowsableObject<Integer> {
@Id
@Column(name = "pooltask_id")
@@ -119,7 +120,7 @@ public class PoolTask implements ReloadableEntity<Integer> {
this.stepId = stepID;
}
public String getStepID() throws SQLException {
public String getStepID() {
return stepId;
}
@@ -130,4 +131,10 @@ public class PoolTask implements ReloadableEntity<Integer> {
public String getActionID() {
return this.actionId;
}
@Override
public int getType() {
return Constants.POOLTASK;
}
}

View File

@@ -17,6 +17,7 @@ import java.util.Set;
import org.apache.commons.collections4.CollectionUtils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
@@ -47,6 +48,11 @@ public class PoolTaskServiceImpl implements PoolTaskService {
}
@Override
public int getSupportsTypeConstant() {
return Constants.POOLTASK;
}
@Override
public List<PoolTask> findByEperson(Context context, EPerson ePerson)
throws SQLException, AuthorizeException, IOException {
@@ -135,6 +141,14 @@ public class PoolTaskServiceImpl implements PoolTaskService {
return poolTaskDAO.findByID(context, PoolTask.class, id);
}
@Override
public PoolTask find(Context context, Integer id) throws SQLException {
if (id == null) {
return null;
}
return find(context, id.intValue());
}
@Override
public void update(Context context, PoolTask poolTask) throws SQLException, AuthorizeException {
update(context, Collections.singletonList(poolTask));

View File

@@ -8,6 +8,7 @@
package org.dspace.xmlworkflow.storedcomponents;
import java.sql.SQLException;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -20,8 +21,10 @@ import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.dspace.browse.BrowsableObject;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.ReloadableEntity;
import org.dspace.eperson.EPerson;
@@ -37,7 +40,7 @@ import org.dspace.workflow.WorkflowItem;
*/
@Entity
@Table(name = "cwf_workflowitem")
public class XmlWorkflowItem implements WorkflowItem, ReloadableEntity<Integer> {
public class XmlWorkflowItem implements WorkflowItem, ReloadableEntity<Integer>, BrowsableObject<Integer> {
@Id
@Column(name = "workflowitem_id")
@@ -134,4 +137,16 @@ public class XmlWorkflowItem implements WorkflowItem, ReloadableEntity<Integer>
this.publishedBefore = b;
}
@Override
public int getState() {
// FIXME not used by the xml workflow, should be removed when the basic workflow is removed and the interfaces
// simplified
return 0;
}
@Override
public int getType() {
return Constants.WORKFLOWITEM;
}
}

View File

@@ -17,9 +17,11 @@ import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
import org.dspace.xmlworkflow.service.WorkflowRequirementsService;
import org.dspace.xmlworkflow.storedcomponents.dao.XmlWorkflowItemDAO;
import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService;
import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService;
@@ -47,6 +49,8 @@ public class XmlWorkflowItemServiceImpl implements XmlWorkflowItemService {
@Autowired(required = true)
protected PoolTaskService poolTaskService;
@Autowired(required = true)
protected WorkflowRequirementsService workflowRequirementsService;
@Autowired(required = true)
protected WorkflowItemRoleService workflowItemRoleService;
/*
@@ -59,6 +63,11 @@ public class XmlWorkflowItemServiceImpl implements XmlWorkflowItemService {
}
@Override
public int getSupportsTypeConstant() {
return Constants.WORKFLOWITEM;
}
@Override
public XmlWorkflowItem create(Context context, Item item, Collection collection)
throws SQLException, AuthorizeException {
@@ -69,7 +78,7 @@ public class XmlWorkflowItemServiceImpl implements XmlWorkflowItemService {
}
@Override
public XmlWorkflowItem find(Context context, int id) throws SQLException {
public XmlWorkflowItem find(Context context, Integer id) throws SQLException {
XmlWorkflowItem workflowItem = xmlWorkflowItemDAO.findByID(context, XmlWorkflowItem.class, id);
@@ -93,13 +102,17 @@ public class XmlWorkflowItemServiceImpl implements XmlWorkflowItemService {
}
@Override
public List<XmlWorkflowItem> findAll(Context context, Integer offset, Integer pagesize) throws SQLException {
return findAllInCollection(context, offset, pagesize, null);
public List<XmlWorkflowItem> findAll(Context context, Integer page, Integer pagesize) throws SQLException {
return findAllInCollection(context, page, pagesize, null);
}
@Override
public List<XmlWorkflowItem> findAllInCollection(Context context, Integer offset, Integer pagesize,
public List<XmlWorkflowItem> findAllInCollection(Context context, Integer page, Integer pagesize,
Collection collection) throws SQLException {
Integer offset = null;
if (page != null && pagesize != null) {
offset = page * pagesize;
}
return xmlWorkflowItemDAO.findAllInCollection(context, offset, pagesize, collection);
}
@@ -118,6 +131,21 @@ public class XmlWorkflowItemServiceImpl implements XmlWorkflowItemService {
return xmlWorkflowItemDAO.findBySubmitter(context, ep);
}
@Override
public List<XmlWorkflowItem> findBySubmitter(Context context, EPerson ep, Integer pageNumber, Integer pageSize)
throws SQLException {
Integer offset = null;
if (pageNumber != null && pageSize != null) {
offset = pageNumber * pageSize;
}
return xmlWorkflowItemDAO.findBySubmitter(context, ep, pageNumber, pageSize);
}
@Override
public int countBySubmitter(Context context, EPerson ep) throws SQLException {
return xmlWorkflowItemDAO.countBySubmitter(context, ep);
}
@Override
public void deleteByCollection(Context context, Collection collection)
throws SQLException, IOException, AuthorizeException {
@@ -175,6 +203,7 @@ public class XmlWorkflowItemServiceImpl implements XmlWorkflowItemService {
}
poolTaskService.deleteByWorkflowItem(context, workflowItem);
workflowRequirementsService.clearInProgressUsers(context, workflowItem);
claimedTaskService.deleteByWorkflowItem(context, workflowItem);
// FIXME - auth?

View File

@@ -13,6 +13,7 @@ import java.util.List;
import org.dspace.content.Collection;
import org.dspace.core.Context;
import org.dspace.core.GenericDAO;
import org.dspace.eperson.Group;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
/**
@@ -27,6 +28,17 @@ public interface CollectionRoleDAO extends GenericDAO<CollectionRole> {
public List<CollectionRole> findByCollection(Context context, Collection collection) throws SQLException;
/**
*
* @param context
* DSpace context
* @param group
* EPerson Group
* @return the list of CollectionRole assigned to the specified group
* @throws SQLException
*/
public List<CollectionRole> findByGroup(Context context, Group group) throws SQLException;
public CollectionRole findByCollectionAndRole(Context context, Collection collection, String role)
throws SQLException;

View File

@@ -27,6 +27,20 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
*/
public interface XmlWorkflowItemDAO extends GenericDAO<XmlWorkflowItem> {
/**
* Find all the workflow items in a specific collection using the pagination parameters (offset, limit)
*
* @param context
* dspace context
* @param offset
* the first record to return
* @param limit
* the max number of records to return
* @param collection
* the collection where the workflowitem has been submitted
* @return all the workflow items respecting the parameters conditions
* @throws SQLException
*/
public List<XmlWorkflowItem> findAllInCollection(Context context, Integer offset, Integer limit,
Collection collection) throws SQLException;
@@ -39,4 +53,32 @@ public interface XmlWorkflowItemDAO extends GenericDAO<XmlWorkflowItem> {
public List<XmlWorkflowItem> findByCollection(Context context, Collection collection) throws SQLException;
public XmlWorkflowItem findByItem(Context context, Item item) throws SQLException;
/**
* Return all the workflow items from a specific submitter respecting the pagination parameters
*
* @param context
* The relevant DSpace Context.
* @param ep
* the eperson that has submitted the item
* @param offset
* the first record to return
* @param limit
* the max number of records to return
* @return
*/
public List<XmlWorkflowItem> findBySubmitter(Context context, EPerson ep, Integer offset, Integer limit)
throws SQLException;
/**
* Count the number of workflow items from a specific submitter
*
* @param context
* The relevant DSpace Context.
* @param ep
* the eperson that has submitted the item
* @return
* @throws SQLException
*/
public int countBySubmitter(Context context, EPerson ep) throws SQLException;
}

View File

@@ -17,6 +17,7 @@ import javax.persistence.criteria.Root;
import org.dspace.content.Collection;
import org.dspace.core.AbstractHibernateDAO;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
import org.dspace.xmlworkflow.storedcomponents.CollectionRole_;
import org.dspace.xmlworkflow.storedcomponents.dao.CollectionRoleDAO;
@@ -43,6 +44,16 @@ public class CollectionRoleDAOImpl extends AbstractHibernateDAO<CollectionRole>
return list(context, criteriaQuery, false, CollectionRole.class, -1, -1);
}
@Override
public List<CollectionRole> findByGroup(Context context, Group group) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, CollectionRole.class);
Root<CollectionRole> collectionRoleRoot = criteriaQuery.from(CollectionRole.class);
criteriaQuery.select(collectionRoleRoot);
criteriaQuery.where(criteriaBuilder.equal(collectionRoleRoot.get(CollectionRole_.group), group));
return list(context, criteriaQuery, false, CollectionRole.class, -1, -1);
}
@Override
public CollectionRole findByCollectionAndRole(Context context, Collection collection, String role)
throws SQLException {

View File

@@ -56,6 +56,7 @@ public class XmlWorkflowItemDAOImpl extends AbstractHibernateDAO<XmlWorkflowItem
if (limit == null) {
limit = -1;
}
criteriaQuery.orderBy(criteriaBuilder.asc(xmlWorkflowItemRoot.get(XmlWorkflowItem_.id)));
return list(context, criteriaQuery, false, XmlWorkflowItem.class, limit, offset);
}
@@ -81,6 +82,18 @@ public class XmlWorkflowItemDAOImpl extends AbstractHibernateDAO<XmlWorkflowItem
@Override
public List<XmlWorkflowItem> findBySubmitter(Context context, EPerson ep) throws SQLException {
return findBySubmitter(context, ep, null, null);
}
@Override
public List<XmlWorkflowItem> findBySubmitter(Context context, EPerson ep, Integer offset, Integer limit)
throws SQLException {
if (offset == null) {
offset = -1;
}
if (limit == null) {
limit = -1;
}
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, XmlWorkflowItem.class);
@@ -88,7 +101,18 @@ public class XmlWorkflowItemDAOImpl extends AbstractHibernateDAO<XmlWorkflowItem
Join<XmlWorkflowItem, Item> join = xmlWorkflowItemRoot.join("item");
criteriaQuery.select(xmlWorkflowItemRoot);
criteriaQuery.where(criteriaBuilder.equal(join.get(Item_.submitter), ep));
return list(context, criteriaQuery, false, XmlWorkflowItem.class, -1, -1);
criteriaQuery.orderBy(criteriaBuilder.asc(xmlWorkflowItemRoot.get(XmlWorkflowItem_.id)));
return list(context, criteriaQuery, false, XmlWorkflowItem.class, limit, offset);
}
@Override
public int countBySubmitter(Context context, EPerson ep) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery<Long> criteriaQuery = criteriaBuilder.createQuery(Long.class);
Root<XmlWorkflowItem> xmlWorkflowItemRoot = criteriaQuery.from(XmlWorkflowItem.class);
Join<XmlWorkflowItem, Item> join = xmlWorkflowItemRoot.join("item");
criteriaQuery.where(criteriaBuilder.equal(join.get(Item_.submitter), ep));
return count(context, criteriaQuery, criteriaBuilder, xmlWorkflowItemRoot);
}
@Override
@@ -98,6 +122,7 @@ public class XmlWorkflowItemDAOImpl extends AbstractHibernateDAO<XmlWorkflowItem
Root<XmlWorkflowItem> xmlWorkflowItemRoot = criteriaQuery.from(XmlWorkflowItem.class);
criteriaQuery.select(xmlWorkflowItemRoot);
criteriaQuery.where(criteriaBuilder.equal(xmlWorkflowItemRoot.get(XmlWorkflowItem_.collection), collection));
criteriaQuery.orderBy(criteriaBuilder.asc(xmlWorkflowItemRoot.get(XmlWorkflowItem_.id)));
return list(context, criteriaQuery, false, XmlWorkflowItem.class, -1, -1);
}

View File

@@ -11,6 +11,7 @@ import java.sql.SQLException;
import java.util.List;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.service.BrowsableObjectService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.service.DSpaceCRUDService;
@@ -24,7 +25,8 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
*
* @author kevinvandevelde at atmire.com
*/
public interface ClaimedTaskService extends DSpaceCRUDService<ClaimedTask> {
public interface ClaimedTaskService extends DSpaceCRUDService<ClaimedTask>,
BrowsableObjectService<ClaimedTask, Integer> {
public List<ClaimedTask> findByWorkflowItem(Context context, XmlWorkflowItem workflowItem) throws SQLException;

View File

@@ -24,10 +24,39 @@ import org.dspace.xmlworkflow.storedcomponents.CollectionRole;
*/
public interface CollectionRoleService {
/**
* This is the default name of the role equivalent in the default configuration to the "legacy" workflow step1. Old
* piece of code will expect to use it in place of the workflow step1
*/
public final String LEGACY_WORKFLOW_STEP1_NAME = "reviewer";
/**
* This is the default name of the role equivalent in the default configuration to the "legacy" workflow step2. Old
* piece of code will expect to use it in place of the workflow step2
*/
public final String LEGACY_WORKFLOW_STEP2_NAME = "editor";
/**
* This is the default name of the role equivalent in the default configuration to the "legacy" workflow step3. Old
* piece of code will expect to use it in place of the workflow step3
*/
public final String LEGACY_WORKFLOW_STEP3_NAME = "finaleditor";
public CollectionRole find(Context context, int id) throws SQLException;
public CollectionRole find(Context context, Collection collection, String role) throws SQLException;
/**
*
* @param context
* DSpace context
* @param group
* EPerson Group
* @return the list of CollectionRole assigned to the specified group
* @throws SQLException
*/
public List<CollectionRole> findByGroup(Context context, Group group) throws SQLException;
public List<CollectionRole> findByCollection(Context context, Collection collection) throws SQLException;
public CollectionRole create(Context context, Collection collection, String roleId, Group group)

View File

@@ -12,6 +12,7 @@ import java.sql.SQLException;
import java.util.List;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.service.BrowsableObjectService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.service.DSpaceCRUDService;
@@ -25,7 +26,7 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
*
* @author kevinvandevelde at atmire.com
*/
public interface PoolTaskService extends DSpaceCRUDService<PoolTask> {
public interface PoolTaskService extends DSpaceCRUDService<PoolTask>, BrowsableObjectService<PoolTask, Integer> {
public List<PoolTask> findByEperson(Context context, EPerson ePerson)
throws SQLException, AuthorizeException, IOException;

View File

@@ -12,6 +12,7 @@ import java.util.List;
import org.dspace.content.Collection;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.workflow.WorkflowItemService;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
@@ -67,4 +68,33 @@ public interface XmlWorkflowItemService extends WorkflowItemService<XmlWorkflowI
*/
public int countAllInCollection(Context context, Collection collection) throws SQLException;
/**
* Return all the workflow items from a specific submitter respecting the pagination parameters
*
* @param context
* The relevant DSpace Context.
* @param ep
* the eperson that has submitted the item
* @param pageNumber
* paging: page number
* @param pageSize
* paging: items per page
* @return
* @throws SQLException
*/
public List<XmlWorkflowItem> findBySubmitter(Context context, EPerson ep, Integer pageNumber, Integer pageSize)
throws SQLException;
/**
* Count the number of workflow items from a specific submitter
*
* @param context
* The relevant DSpace Context.
* @param ep
* the eperson that has submitted the item
* @return
* @throws SQLException
*/
public int countBySubmitter(Context context, EPerson ep) throws SQLException;
}

View File

@@ -0,0 +1,24 @@
--
-- 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/
--
-- ===============================================================
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
--
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
-- http://flywaydb.org/
-- ===============================================================
----------------------------------------------------------------------------------------------------------------
-- This adds TYPE_INHERITED to all old archived items permission due to the change on resource policy management
----------------------------------------------------------------------------------------------------------------
UPDATE resourcepolicy set rptype = 'TYPE_INHERITED'
where resource_type_id = 2 and rptype is null
and dspace_object in (
select uuid from item where in_archive = 1
);

View File

@@ -0,0 +1,24 @@
--
-- 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/
--
-- ===============================================================
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
--
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
-- http://flywaydb.org/
-- ===============================================================
----------------------------------------------------------------------------------------------------------------
-- This adds TYPE_INHERITED to all old archived items permission due to the change on resource policy management
----------------------------------------------------------------------------------------------------------------
UPDATE resourcepolicy set rptype = 'TYPE_INHERITED'
where resource_type_id = 2 and rptype is null
and dspace_object in (
select uuid from item where in_archive = true
);

View File

@@ -0,0 +1,152 @@
--
-- 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-2701 Service based API / Hibernate integration
------------------------------------------------------
UPDATE collection SET workflow_step_1 = null;
UPDATE collection SET workflow_step_2 = null;
UPDATE collection SET workflow_step_3 = null;
-- cwf_workflowitem
DROP INDEX cwf_workflowitem_coll_fk_idx;
ALTER TABLE cwf_workflowitem ALTER COLUMN item_id RENAME TO item_legacy_id;
ALTER TABLE cwf_workflowitem ADD COLUMN item_id UUID;
ALTER TABLE cwf_workflowitem ADD FOREIGN KEY (item_id) REFERENCES Item(uuid);
UPDATE cwf_workflowitem SET item_id = (SELECT item.uuid FROM item WHERE cwf_workflowitem.item_legacy_id = item.item_id);
ALTER TABLE cwf_workflowitem DROP COLUMN item_legacy_id;
ALTER TABLE cwf_workflowitem ALTER COLUMN collection_id RENAME TO collection_legacy_id;
ALTER TABLE cwf_workflowitem ADD COLUMN collection_id UUID;
ALTER TABLE cwf_workflowitem ADD FOREIGN KEY (collection_id) REFERENCES Collection(uuid);
UPDATE cwf_workflowitem SET collection_id = (SELECT collection.uuid FROM collection WHERE cwf_workflowitem.collection_legacy_id = collection.collection_id);
ALTER TABLE cwf_workflowitem DROP COLUMN collection_legacy_id;
UPDATE cwf_workflowitem SET multiple_titles = '0' WHERE multiple_titles IS NULL;
UPDATE cwf_workflowitem SET published_before = '0' WHERE published_before IS NULL;
UPDATE cwf_workflowitem SET multiple_files = '0' WHERE multiple_files IS NULL;
CREATE INDEX cwf_workflowitem_coll_fk_idx ON cwf_workflowitem(collection_id);
-- cwf_collectionrole
ALTER TABLE cwf_collectionrole DROP CONSTRAINT cwf_collectionrole_unique;
DROP INDEX cwf_cr_coll_role_fk_idx;
DROP INDEX cwf_cr_coll_fk_idx;
ALTER TABLE cwf_collectionrole ALTER COLUMN collection_id RENAME TO collection_legacy_id;
ALTER TABLE cwf_collectionrole ADD COLUMN collection_id UUID;
ALTER TABLE cwf_collectionrole ADD FOREIGN KEY (collection_id) REFERENCES Collection(uuid);
UPDATE cwf_collectionrole SET collection_id = (SELECT collection.uuid FROM collection WHERE cwf_collectionrole.collection_legacy_id = collection.collection_id);
ALTER TABLE cwf_collectionrole DROP COLUMN collection_legacy_id;
ALTER TABLE cwf_collectionrole ALTER COLUMN group_id RENAME TO group_legacy_id;
ALTER TABLE cwf_collectionrole ADD COLUMN group_id UUID;
ALTER TABLE cwf_collectionrole ADD FOREIGN KEY (group_id) REFERENCES epersongroup(uuid);
UPDATE cwf_collectionrole SET group_id = (SELECT epersongroup.uuid FROM epersongroup WHERE cwf_collectionrole.group_legacy_id = epersongroup.eperson_group_id);
ALTER TABLE cwf_collectionrole DROP COLUMN group_legacy_id;
ALTER TABLE cwf_collectionrole
ADD CONSTRAINT cwf_collectionrole_unique UNIQUE (role_id, collection_id, group_id);
CREATE INDEX cwf_cr_coll_role_fk_idx ON cwf_collectionrole(collection_id,role_id);
CREATE INDEX cwf_cr_coll_fk_idx ON cwf_collectionrole(collection_id);
-- cwf_workflowitemrole
ALTER TABLE cwf_workflowitemrole DROP CONSTRAINT cwf_workflowitemrole_unique;
DROP INDEX cwf_wfir_item_role_fk_idx;
DROP INDEX cwf_wfir_item_fk_idx;
ALTER TABLE cwf_workflowitemrole ALTER COLUMN group_id RENAME TO group_legacy_id;
ALTER TABLE cwf_workflowitemrole ADD COLUMN group_id UUID;
ALTER TABLE cwf_workflowitemrole ADD FOREIGN KEY (group_id) REFERENCES epersongroup(uuid);
UPDATE cwf_workflowitemrole SET group_id = (SELECT epersongroup.uuid FROM epersongroup WHERE cwf_workflowitemrole.group_legacy_id = epersongroup.eperson_group_id);
ALTER TABLE cwf_workflowitemrole DROP COLUMN group_legacy_id;
ALTER TABLE cwf_workflowitemrole ALTER COLUMN eperson_id RENAME TO eperson_legacy_id;
ALTER TABLE cwf_workflowitemrole ADD COLUMN eperson_id UUID;
ALTER TABLE cwf_workflowitemrole ADD FOREIGN KEY (eperson_id) REFERENCES eperson(uuid);
UPDATE cwf_workflowitemrole SET eperson_id = (SELECT eperson.uuid FROM eperson WHERE cwf_workflowitemrole.eperson_legacy_id = eperson.eperson_id);
ALTER TABLE cwf_workflowitemrole DROP COLUMN eperson_legacy_id;
ALTER TABLE cwf_workflowitemrole
ADD CONSTRAINT cwf_workflowitemrole_unique UNIQUE (role_id, workflowitem_id, eperson_id, group_id);
CREATE INDEX cwf_wfir_item_role_fk_idx ON cwf_workflowitemrole(workflowitem_id,role_id);
CREATE INDEX cwf_wfir_item_fk_idx ON cwf_workflowitemrole(workflowitem_id);
-- cwf_pooltask
DROP INDEX cwf_pt_eperson_fk_idx;
DROP INDEX cwf_pt_workflow_eperson_fk_idx;
ALTER TABLE cwf_pooltask ALTER COLUMN group_id RENAME TO group_legacy_id;
ALTER TABLE cwf_pooltask ADD COLUMN group_id UUID;
ALTER TABLE cwf_pooltask ADD FOREIGN KEY (group_id) REFERENCES epersongroup(uuid);
UPDATE cwf_pooltask SET group_id = (SELECT epersongroup.uuid FROM epersongroup WHERE cwf_pooltask.group_legacy_id = epersongroup.eperson_group_id);
ALTER TABLE cwf_pooltask DROP COLUMN group_legacy_id;
ALTER TABLE cwf_pooltask ALTER COLUMN eperson_id RENAME TO eperson_legacy_id;
ALTER TABLE cwf_pooltask ADD COLUMN eperson_id UUID;
ALTER TABLE cwf_pooltask ADD FOREIGN KEY (eperson_id) REFERENCES eperson(uuid);
UPDATE cwf_pooltask SET eperson_id = (SELECT eperson.uuid FROM eperson WHERE cwf_pooltask.eperson_legacy_id = eperson.eperson_id);
ALTER TABLE cwf_pooltask DROP COLUMN eperson_legacy_id;
CREATE INDEX cwf_pt_eperson_fk_idx ON cwf_pooltask(eperson_id);
CREATE INDEX cwf_pt_workflow_eperson_fk_idx ON cwf_pooltask(eperson_id,workflowitem_id);
-- cwf_claimtask
ALTER TABLE cwf_claimtask DROP CONSTRAINT cwf_claimtask_unique;
DROP INDEX cwf_ct_workflow_fk_idx;
DROP INDEX cwf_ct_workflow_eperson_fk_idx;
DROP INDEX cwf_ct_eperson_fk_idx;
DROP INDEX cwf_ct_wfs_fk_idx;
DROP INDEX cwf_ct_wfs_action_fk_idx;
DROP INDEX cwf_ct_wfs_action_e_fk_idx;
ALTER TABLE cwf_claimtask ALTER COLUMN owner_id RENAME TO eperson_legacy_id;
ALTER TABLE cwf_claimtask ADD COLUMN owner_id UUID;
ALTER TABLE cwf_claimtask ADD FOREIGN KEY (owner_id) REFERENCES eperson(uuid);
UPDATE cwf_claimtask SET owner_id = (SELECT eperson.uuid FROM eperson WHERE cwf_claimtask.eperson_legacy_id = eperson.eperson_id);
ALTER TABLE cwf_claimtask DROP COLUMN eperson_legacy_id;
ALTER TABLE cwf_claimtask
ADD CONSTRAINT cwf_claimtask_unique UNIQUE (step_id, workflowitem_id, workflow_id, owner_id, action_id);
CREATE INDEX cwf_ct_workflow_fk_idx ON cwf_claimtask(workflowitem_id);
CREATE INDEX cwf_ct_workflow_eperson_fk_idx ON cwf_claimtask(workflowitem_id,owner_id);
CREATE INDEX cwf_ct_eperson_fk_idx ON cwf_claimtask(owner_id);
CREATE INDEX cwf_ct_wfs_fk_idx ON cwf_claimtask(workflowitem_id,step_id);
CREATE INDEX cwf_ct_wfs_action_fk_idx ON cwf_claimtask(workflowitem_id,step_id,action_id);
CREATE INDEX cwf_ct_wfs_action_e_fk_idx ON cwf_claimtask(workflowitem_id,step_id,action_id,owner_id);
-- cwf_in_progress_user
ALTER TABLE cwf_in_progress_user DROP CONSTRAINT cwf_in_progress_user_unique;
DROP INDEX cwf_ipu_workflow_fk_idx;
DROP INDEX cwf_ipu_eperson_fk_idx;
ALTER TABLE cwf_in_progress_user ALTER COLUMN user_id RENAME TO eperson_legacy_id;
ALTER TABLE cwf_in_progress_user ADD COLUMN user_id UUID;
ALTER TABLE cwf_in_progress_user ADD FOREIGN KEY (user_id) REFERENCES eperson(uuid);
UPDATE cwf_in_progress_user SET user_id = (SELECT eperson.uuid FROM eperson WHERE cwf_in_progress_user.eperson_legacy_id = eperson.eperson_id);
ALTER TABLE cwf_in_progress_user DROP COLUMN eperson_legacy_id;
UPDATE cwf_in_progress_user SET finished = '0' WHERE finished IS NULL;
ALTER TABLE cwf_in_progress_user
ADD CONSTRAINT cwf_in_progress_user_unique UNIQUE (workflowitem_id, user_id);
CREATE INDEX cwf_ipu_workflow_fk_idx ON cwf_in_progress_user(workflowitem_id);
CREATE INDEX cwf_ipu_eperson_fk_idx ON cwf_in_progress_user(user_id);

View File

@@ -0,0 +1,27 @@
--
-- 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/
--
-- UPDATE policies for claimtasks
-- Item
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id JOIN item ON cwf_workflowitem.item_id = item.uuid) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bundles
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT item2bundle.bundle_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bitstreams
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT bundle2bitstream.bitstream_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id INNER JOIN bundle2bitstream ON item2bundle.bundle_id = bundle2bitstream.bundle_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Create policies for pooled tasks
-- Item
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bundles
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bitstreams
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id INNER JOIN bundle2bitstream ON item2bundle.bundle_id = bundle2bitstream.bundle_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);

View File

@@ -0,0 +1,27 @@
--
-- 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/
--
-- UPDATE policies for claimtasks
-- Item
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id JOIN item ON cwf_workflowitem.item_id = item.uuid) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bundles
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT item2bundle.bundle_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bitstreams
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT bundle2bitstream.bitstream_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id INNER JOIN bundle2bitstream ON item2bundle.bundle_id = bundle2bitstream.bundle_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Create policies for pooled tasks
-- Item
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bundles
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bitstreams
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id INNER JOIN bundle2bitstream ON item2bundle.bundle_id = bundle2bitstream.bundle_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);

View File

@@ -0,0 +1,27 @@
--
-- 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/
--
-- UPDATE policies for claimtasks
-- Item
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id JOIN item ON cwf_workflowitem.item_id = item.uuid) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bundles
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT item2bundle.bundle_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bitstreams
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT bundle2bitstream.bitstream_id FROM cwf_workflowitem INNER JOIN cwf_claimtask ON cwf_workflowitem.workflowitem_id = cwf_claimtask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id INNER JOIN bundle2bitstream ON item2bundle.bundle_id = bundle2bitstream.bundle_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Create policies for pooled tasks
-- Item
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bundles
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);
-- Bitstreams
UPDATE RESOURCEPOLICY SET rptype = 'TYPE_WORKFLOW' WHERE dspace_object in (SELECT cwf_workflowitem.item_id FROM cwf_workflowitem INNER JOIN cwf_pooltask ON cwf_workflowitem.workflowitem_id = cwf_pooltask.workflowitem_id INNER JOIN item2bundle ON cwf_workflowitem.item_id = item2bundle.item_id INNER JOIN bundle2bitstream ON item2bundle.bundle_id = bundle2bitstream.bundle_id) AND eperson_id not in (SELECT item.submitter_id FROM cwf_workflowitem JOIN item ON cwf_workflowitem.item_id = item.uuid);

View File

@@ -0,0 +1,23 @@
--
-- 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/
--
----------------------------------------------------
-- Data Migration for XML/Configurable Workflow
--
-- This file will automatically migrate existing
-- classic workflows to XML/Configurable workflows.
-- NOTE however that the corresponding
-- "xml_workflow_migration.sql" script must FIRST be
-- called to create the appropriate database tables.
--
-- This script is called automatically by the following
-- Flyway Java migration class:
-- org.dspace.storage.rdbms.migration.V5_0_2014_01_01__XMLWorkflow_Migration
----------------------------------------------------
-- No data to convert in the H2 in memory test database

View File

@@ -0,0 +1,27 @@
--
-- 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/
--
----------------------------------------------------
-- Data Migration for XML/Configurable Workflow
--
-- This file will automatically migrate existing
-- classic workflows to XML/Configurable workflows.
-- NOTE however that the corresponding
-- "xml_workflow_migration.sql" script must FIRST be
-- called to create the appropriate database tables.
--
-- This script is called automatically by the following
-- Flyway Java migration class:
-- org.dspace.storage.rdbms.xmlworkflow.V6_0_2015_09_01__DS_2701_Enable_XMLWorkflow_Migration
----------------------------------------------------
-- Convert workflow groups:
-- TODO: is 'to_number' ok? do not forget to change role_id values
--
-- Nothing here as the H2 in memory database is always a fresh installation
-- so the xml workflow is already activated in version 5

View File

@@ -0,0 +1,24 @@
--
-- 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/
--
----------------------------------------------------
-- Database Schema Update for XML/Configurable Workflow (for DSpace 6.0)
--
-- This file will automatically create/update your
-- DSpace Database tables to support XML/Configurable workflows.
-- However, it does NOT migrate your existing classic
-- workflows. That step is performed by the corresponding
-- "data_workflow_migration.sql" script.
--
-- This script is called automatically by the following
-- Flyway Java migration class:
-- org.dspace.storage.rdbms.xmlworkflow.V6_0_2015_09_01__DS_2701_Enable_XMLWorkflow_Migration
----------------------------------------------------
--
-- Nothing here as the H2 in memory database is always a fresh installation
-- so the xml workflow is already activated in version 5

View File

@@ -0,0 +1,124 @@
--
-- 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/
--
----------------------------------------------------
-- Database Schema Update for XML/Configurable Workflow
--
-- This file will automatically create/update your
-- DSpace Database tables to support XML/Configurable workflows.
-- However, it does NOT migrate your existing classic
-- workflows. That step is performed by the corresponding
-- "data_workflow_migration.sql" script.
--
-- This script is called automatically by the following
-- Flyway Java migration class:
-- org.dspace.storage.rdbms.migration.V5_0_2014_01_01__XMLWorkflow_Migration
----------------------------------------------------
CREATE SEQUENCE cwf_workflowitem_seq;
CREATE SEQUENCE cwf_collectionrole_seq;
CREATE SEQUENCE cwf_workflowitemrole_seq;
CREATE SEQUENCE cwf_claimtask_seq;
CREATE SEQUENCE cwf_in_progress_user_seq;
CREATE SEQUENCE cwf_pooltask_seq;
CREATE TABLE cwf_workflowitem
(
workflowitem_id INTEGER PRIMARY KEY,
item_id INTEGER UNIQUE REFERENCES item(item_id),
collection_id INTEGER REFERENCES collection(collection_id),
--
-- Answers to questions on first page of submit UI
multiple_titles BOOLEAN,
published_before BOOLEAN,
multiple_files BOOLEAN
-- Note: stage reached not applicable here - people involved in workflow
-- can always jump around submission UI
);
CREATE INDEX cwf_workflowitem_coll_fk_idx ON cwf_workflowitem(collection_id);
CREATE TABLE cwf_collectionrole (
collectionrole_id INTEGER PRIMARY KEY,
role_id VARCHAR2(256),
collection_id integer REFERENCES collection(collection_id),
group_id integer REFERENCES epersongroup(eperson_group_id)
);
ALTER TABLE cwf_collectionrole
ADD CONSTRAINT cwf_collectionrole_unique UNIQUE (role_id, collection_id, group_id);
CREATE INDEX cwf_cr_coll_role_fk_idx ON cwf_collectionrole(collection_id,role_id);
CREATE INDEX cwf_cr_coll_fk_idx ON cwf_collectionrole(collection_id);
CREATE TABLE cwf_workflowitemrole (
workflowitemrole_id INTEGER PRIMARY KEY,
role_id VARCHAR2(256),
workflowitem_id integer REFERENCES cwf_workflowitem(workflowitem_id),
eperson_id integer REFERENCES eperson(eperson_id),
group_id integer REFERENCES epersongroup(eperson_group_id)
);
ALTER TABLE cwf_workflowitemrole
ADD CONSTRAINT cwf_workflowitemrole_unique UNIQUE (role_id, workflowitem_id, eperson_id, group_id);
CREATE INDEX cwf_wfir_item_role_fk_idx ON cwf_workflowitemrole(workflowitem_id,role_id);
CREATE INDEX cwf_wfir_item_fk_idx ON cwf_workflowitemrole(workflowitem_id);
CREATE TABLE cwf_pooltask (
pooltask_id INTEGER PRIMARY KEY,
workflowitem_id INTEGER REFERENCES cwf_workflowitem(workflowitem_id),
workflow_id VARCHAR2(256),
step_id VARCHAR2(256),
action_id VARCHAR2(256),
eperson_id INTEGER REFERENCES EPerson(eperson_id),
group_id INTEGER REFERENCES epersongroup(eperson_group_id)
);
CREATE INDEX cwf_pt_eperson_fk_idx ON cwf_pooltask(eperson_id);
CREATE INDEX cwf_pt_workflow_fk_idx ON cwf_pooltask(workflowitem_id);
CREATE INDEX cwf_pt_workflow_eperson_fk_idx ON cwf_pooltask(eperson_id,workflowitem_id);
CREATE TABLE cwf_claimtask (
claimtask_id INTEGER PRIMARY KEY,
workflowitem_id integer REFERENCES cwf_workflowitem(workflowitem_id),
workflow_id VARCHAR2(256),
step_id VARCHAR2(256),
action_id VARCHAR2(256),
owner_id integer REFERENCES eperson(eperson_id)
);
ALTER TABLE cwf_claimtask
ADD CONSTRAINT cwf_claimtask_unique UNIQUE (step_id, workflowitem_id, workflow_id, owner_id, action_id);
CREATE INDEX cwf_ct_workflow_fk_idx ON cwf_claimtask(workflowitem_id);
CREATE INDEX cwf_ct_workflow_eperson_fk_idx ON cwf_claimtask(workflowitem_id,owner_id);
CREATE INDEX cwf_ct_eperson_fk_idx ON cwf_claimtask(owner_id);
CREATE INDEX cwf_ct_wfs_fk_idx ON cwf_claimtask(workflowitem_id,step_id);
CREATE INDEX cwf_ct_wfs_action_fk_idx ON cwf_claimtask(workflowitem_id,step_id,action_id);
CREATE INDEX cwf_ct_wfs_action_e_fk_idx ON cwf_claimtask(workflowitem_id,step_id,action_id,owner_id);
CREATE TABLE cwf_in_progress_user (
in_progress_user_id INTEGER PRIMARY KEY,
workflowitem_id integer REFERENCES cwf_workflowitem(workflowitem_id),
user_id integer REFERENCES eperson(eperson_id),
finished BOOLEAN DEFAULT 0
);
ALTER TABLE cwf_in_progress_user
ADD CONSTRAINT cwf_in_progress_user_unique UNIQUE (workflowitem_id, user_id);
CREATE INDEX cwf_ipu_workflow_fk_idx ON cwf_in_progress_user(workflowitem_id);
CREATE INDEX cwf_ipu_eperson_fk_idx ON cwf_in_progress_user(user_id);

View File

@@ -509,8 +509,9 @@ public class CollectionTest extends AbstractDSpaceObjectTest {
Group g = groupService.create(context);
context.restoreAuthSystemState();
collection.setWorkflowGroup(context, step, g);
assertThat("testSetWorkflowGroup 0", collectionService.getWorkflowGroup(collection, step), notNullValue());
assertThat("testSetWorkflowGroup 1", collectionService.getWorkflowGroup(collection, step), equalTo(g));
assertThat("testSetWorkflowGroup 0", collectionService.getWorkflowGroup(context, collection, step),
notNullValue());
assertThat("testSetWorkflowGroup 1", collectionService.getWorkflowGroup(context, collection, step), equalTo(g));
}
/**
@@ -528,8 +529,10 @@ public class CollectionTest extends AbstractDSpaceObjectTest {
context.restoreAuthSystemState();
collection.setWorkflowGroup(context, step, g1);
collection.setWorkflowGroup(context, step, g2);
assertThat("testSetWorkflowGroup 0", collectionService.getWorkflowGroup(collection, step), notNullValue());
assertThat("testSetWorkflowGroup 1", collectionService.getWorkflowGroup(collection, step), equalTo(g2));
assertThat("testSetWorkflowGroup 0", collectionService.getWorkflowGroup(context, collection, step),
notNullValue());
assertThat("testSetWorkflowGroup 1", collectionService.getWorkflowGroup(context, collection, step),
equalTo(g2));
}
/**
@@ -539,7 +542,8 @@ public class CollectionTest extends AbstractDSpaceObjectTest {
public void testGetWorkflowGroup() {
//null by default
int step = 1;
assertThat("testGetWorkflowGroup 0", collectionService.getWorkflowGroup(collection, step), nullValue());
assertThat("testGetWorkflowGroup 0", collectionService.getWorkflowGroup(context, collection, step),
nullValue());
}
/**

View File

@@ -157,7 +157,7 @@ public class PackageUtilsTest extends AbstractUnitTest {
@Test
public void testCrosswalkGroupNameWithoutUnderscore() throws Exception {
Collection testCollection = (Collection) handleService.resolveToObject(context, testCollectionHandle);
Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1();
Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1(context);
GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
Group testGroup = groupService.create(context);
@@ -179,7 +179,7 @@ public class PackageUtilsTest extends AbstractUnitTest {
@Test
public void testCrosswalkGroupNameUnderscoresNoDSO() throws Exception {
Collection testCollection = (Collection) handleService.resolveToObject(context, testCollectionHandle);
Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1();
Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1(context);
GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
Group testGroup = groupService.create(context);
@@ -201,7 +201,7 @@ public class PackageUtilsTest extends AbstractUnitTest {
@Test
public void testCrosswalkGroupNameUnderscoresAndDSO() throws Exception {
Collection testCollection = (Collection) handleService.resolveToObject(context, testCollectionHandle);
Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1();
Group originalFirstStepWorkflowGroup = testCollection.getWorkflowStep1(context);
Group group = collectionService.createWorkflowGroup(context, testCollection, 1);

View File

@@ -47,6 +47,7 @@ import org.hamcrest.CoreMatchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
@@ -57,6 +58,7 @@ import org.junit.Test;
* @author Pascal-Nicolas Becker
* @author Terry Brady
*/
@Ignore
public class BasicWorkflowAuthorizationIT
extends AbstractIntegrationTest {
/**
@@ -206,7 +208,8 @@ public class BasicWorkflowAuthorizationIT
} finally {
context.restoreAuthSystemState();
}
Assert.assertThat("testsetWorkflowGroupSetsPermission 0", collectionService.getWorkflowGroup(collection, step),
Assert.assertThat("testsetWorkflowGroupSetsPermission 0",
collectionService.getWorkflowGroup(context, collection, step),
CoreMatchers.equalTo(group));
Assert.assertTrue(groupService.isDirectMember(group, member));
Assert.assertTrue("testsetWorkflowGroupSetsPermission 1", authorizeService
@@ -228,7 +231,8 @@ public class BasicWorkflowAuthorizationIT
context.restoreAuthSystemState();
}
Assert
.assertThat("testsetWorkflowGroupRevokesPermission 0", collectionService.getWorkflowGroup(collection, step),
.assertThat("testsetWorkflowGroupRevokesPermission 0",
collectionService.getWorkflowGroup(context, collection, step),
CoreMatchers
.equalTo(group));
Assert.assertTrue("testsetWorkflowGroupRevokesPermission 1", authorizeService
@@ -241,7 +245,8 @@ public class BasicWorkflowAuthorizationIT
context.restoreAuthSystemState();
}
Assert
.assertThat("testsetWorkflowGroupRevokesPermission 2", collectionService.getWorkflowGroup(collection, step),
.assertThat("testsetWorkflowGroupRevokesPermission 2",
collectionService.getWorkflowGroup(context, collection, step),
CoreMatchers
.nullValue());
Assert.assertFalse("testsetWorkflowGroupRevokesPermission 3", authorizeService

View File

@@ -50,6 +50,7 @@ import org.dspace.workflowbasic.service.BasicWorkflowService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
@@ -60,6 +61,7 @@ import org.junit.Test;
* @author Pascal-Nicolas Becker
* @author Terry Brady
*/
@Ignore
public class BasicWorkflowAuthorizationRolesIT
extends AbstractIntegrationTest {
/**
@@ -289,9 +291,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -338,9 +340,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -387,9 +389,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -436,9 +438,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -488,9 +490,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP2POOL, wfi.getState());
@@ -536,9 +538,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP2POOL, wfi.getState());
@@ -584,9 +586,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP2POOL, wfi.getState());
@@ -632,9 +634,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP2POOL, wfi.getState());
@@ -683,9 +685,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP3POOL, wfi.getState());
@@ -731,9 +733,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP3POOL, wfi.getState());
@@ -779,9 +781,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP3POOL, wfi.getState());
@@ -827,9 +829,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP3POOL, wfi.getState());
@@ -878,9 +880,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -926,9 +928,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -974,9 +976,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3());
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertNull(collection.getWorkflowStep3(context));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -1027,9 +1029,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -1075,9 +1077,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -1124,9 +1126,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2());
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertNull(collection.getWorkflowStep2(context));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -1176,9 +1178,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP2POOL, wfi.getState());
@@ -1224,9 +1226,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP2POOL, wfi.getState());
@@ -1272,9 +1274,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertNull(collection.getWorkflowStep1());
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertNull(collection.getWorkflowStep1(context));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP2POOL, wfi.getState());
@@ -1324,9 +1326,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -1380,9 +1382,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());
@@ -1436,9 +1438,9 @@ public class BasicWorkflowAuthorizationRolesIT
try {
contextReload();
Assert.assertEquals(collection.getWorkflowStep1(), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(collection.getWorkflowStep1(context), roleGroups.get(ROLE.STEP1));
Assert.assertEquals(collection.getWorkflowStep2(context), roleGroups.get(ROLE.STEP2));
Assert.assertEquals(collection.getWorkflowStep3(context), roleGroups.get(ROLE.STEP3));
Assert.assertEquals(BasicWorkflowService.WFSTATE_STEP1POOL, wfi.getState());

View File

@@ -492,6 +492,46 @@ public class RestResourceController implements InitializingBean {
}
/**
* Called in POST, with a x-www-form-urlencoded, execute an action on a resource
*
* Note that the regular expression in the request mapping accept a number as identifier;
*
* @param request
* @param apiCategory
* @param model
* @param id
* @return
* @throws HttpRequestMethodNotSupportedException
* @throws IOException
* @throws SQLException
*/
@RequestMapping(method = RequestMethod.POST, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT, headers =
"content-type=application/x-www-form-urlencoded")
public ResponseEntity<ResourceSupport> action(HttpServletRequest request, @PathVariable String apiCategory,
@PathVariable String model, @PathVariable Integer id)
throws HttpRequestMethodNotSupportedException, SQLException, IOException {
checkModelPluralForm(apiCategory, model);
DSpaceRestRepository<RestAddressableModel, Integer> repository =
utils.getResourceRepository(apiCategory, model);
RestAddressableModel modelObject = null;
try {
modelObject = repository.action(request, id);
} catch (UnprocessableEntityException e) {
log.error(e.getMessage(), e);
return ControllerUtils.toEmptyResponse(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (modelObject != null) {
DSpaceResource result = repository.wrapResource(modelObject);
linkService.addLinks(result);
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result);
} else {
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
}
/**
* Called in POST, multipart, upload to a specific rest resource the file passed as "file" request parameter
*

View File

@@ -88,7 +88,8 @@ public class UUIDLookupRestController implements InitializingBean {
Context context = null;
try {
context = ContextUtil.obtainContext(request);
for (DSpaceObjectService dSpaceObjectService : contentServiceFactory.getDSpaceObjectServices()) {
for (DSpaceObjectService<? extends DSpaceObject> dSpaceObjectService : contentServiceFactory
.getDSpaceObjectServices()) {
DSpaceObject dso = dSpaceObjectService.find(context, uuid);
if (dso != null) {
DSpaceObjectRest dsor = converter.convert(dso);

View File

@@ -0,0 +1,153 @@
/**
* 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/
*/
package org.dspace.app.rest.converter;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.model.AInprogressSubmissionRest;
import org.dspace.app.rest.model.ErrorRest;
import org.dspace.app.rest.model.SubmissionDefinitionRest;
import org.dspace.app.rest.model.SubmissionSectionRest;
import org.dspace.app.rest.submit.AbstractRestProcessingStep;
import org.dspace.app.rest.submit.SubmissionService;
import org.dspace.app.util.SubmissionConfigReader;
import org.dspace.app.util.SubmissionConfigReaderException;
import org.dspace.app.util.SubmissionStepConfig;
import org.dspace.content.Collection;
import org.dspace.content.InProgressSubmission;
import org.dspace.content.Item;
import org.dspace.eperson.EPerson;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Abstract implementation providing the common functionalities for all the inprogressSubmission Converter
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*
* @param <T>
* the DSpace API inprogressSubmission object
* @param <R>
* the DSpace REST inprogressSubmission representation
* @param <ID>
* the Serializable class used as primary key
*/
public abstract class AInprogressItemConverter<T extends InProgressSubmission<ID>,
R extends AInprogressSubmissionRest<ID>, ID extends Serializable>
extends BrowsableDSpaceObjectConverter<T, R> {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(AInprogressItemConverter.class);
@Autowired
private EPersonConverter epersonConverter;
@Autowired
private ItemConverter itemConverter;
@Autowired
private CollectionConverter collectionConverter;
protected SubmissionConfigReader submissionConfigReader;
@Autowired
private SubmissionDefinitionConverter submissionDefinitionConverter;
@Autowired
private SubmissionSectionConverter submissionSectionConverter;
@Autowired
SubmissionService submissionService;
public AInprogressItemConverter() throws SubmissionConfigReaderException {
submissionConfigReader = new SubmissionConfigReader();
}
protected void fillFromModel(T obj, R witem) {
Collection collection = obj.getCollection();
Item item = obj.getItem();
EPerson submitter = null;
try {
submitter = obj.getSubmitter();
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
witem.setId(obj.getID());
witem.setCollection(collection != null ? collectionConverter.convert(collection) : null);
witem.setItem(itemConverter.convert(item));
witem.setSubmitter(epersonConverter.convert(submitter));
// 1. retrieve the submission definition
// 2. iterate over the submission section to allow to plugin additional
// info
if (collection != null) {
SubmissionDefinitionRest def = submissionDefinitionConverter
.convert(submissionConfigReader.getSubmissionConfigByCollection(collection.getHandle()));
witem.setSubmissionDefinition(def);
for (SubmissionSectionRest sections : def.getPanels()) {
SubmissionStepConfig stepConfig = submissionSectionConverter.toModel(sections);
/*
* First, load the step processing class (using the current
* class loader)
*/
ClassLoader loader = this.getClass().getClassLoader();
Class stepClass;
try {
stepClass = loader.loadClass(stepConfig.getProcessingClassName());
Object stepInstance = stepClass.newInstance();
if (stepInstance instanceof AbstractRestProcessingStep) {
// load the interface for this step
AbstractRestProcessingStep stepProcessing =
(AbstractRestProcessingStep) stepClass.newInstance();
for (ErrorRest error : stepProcessing.validate(submissionService, obj, stepConfig)) {
addError(witem.getErrors(), error);
}
witem.getSections()
.put(sections.getId(), stepProcessing.getData(submissionService, obj, stepConfig));
} else {
log.warn("The submission step class specified by '" + stepConfig.getProcessingClassName() +
"' does not extend the class org.dspace.app.rest.submit.AbstractRestProcessingStep!" +
" Therefore it cannot be used by the Configurable Submission as the " +
"<processing-class>!");
}
} catch (Exception e) {
log.error("An error occurred during the unmarshal of the data for the section " + sections.getId()
+ " - reported error: " + e.getMessage(), e);
}
}
}
}
private void addError(List<ErrorRest> errors, ErrorRest toAdd) {
boolean found = false;
String i18nKey = toAdd.getMessage();
if (StringUtils.isNotBlank(i18nKey)) {
for (ErrorRest error : errors) {
if (i18nKey.equals(error.getMessage())) {
error.getPaths().addAll(toAdd.getPaths());
found = true;
break;
}
}
}
if (!found) {
errors.add(toAdd);
}
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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/
*/
package org.dspace.app.rest.converter;
import org.dspace.browse.BrowsableObject;
/**
* This is the base converter from/to objects in the DSpace API data model and
* the REST data model that can be indexed
*
* @param <M> the Class in the DSpace API data model
* @param <R> the Class in the DSpace REST data model
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
public abstract class BrowsableDSpaceObjectConverter<M extends BrowsableObject,
R extends org.dspace.app.rest.model.RestAddressableModel> extends DSpaceConverter<M, R> {
/**
*
* @param bdso
* the browsableDSpaceObject to check
* @return true if the actual converter implementation is able to manage the supplied BrowsableDSpaceObject
*/
public abstract boolean supportsModel(BrowsableObject bdso);
}

View File

@@ -0,0 +1,56 @@
/**
* 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/
*/
package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.ClaimedTaskRest;
import org.dspace.browse.BrowsableObject;
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* This is the converter from/to the laimTask in the DSpace API data model
* and the REST data model
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ClaimedTaskConverter
extends BrowsableDSpaceObjectConverter<ClaimedTask, org.dspace.app.rest.model.ClaimedTaskRest> {
@Autowired
private WorkflowItemConverter workflowItemConverter;
@Autowired
private EPersonConverter epersonConverter;
@Override
public ClaimedTaskRest fromModel(ClaimedTask obj) {
ClaimedTaskRest taskRest = new ClaimedTaskRest();
XmlWorkflowItem witem = obj.getWorkflowItem();
taskRest.setId(obj.getID());
taskRest.setWorkflowitem(workflowItemConverter.convert(witem));
taskRest.setAction(obj.getActionID());
taskRest.setStep(obj.getStepID());
taskRest.setOwner(epersonConverter.convert(obj.getOwner()));
return taskRest;
}
@Override
public ClaimedTask toModel(ClaimedTaskRest obj) {
return null;
}
@Override
public boolean supportsModel(BrowsableObject object) {
return object instanceof ClaimedTask;
}
}

View File

@@ -7,6 +7,7 @@
*/
package org.dspace.app.rest.converter;
import org.dspace.browse.BrowsableObject;
import org.dspace.content.DSpaceObject;
import org.springframework.beans.factory.annotation.Autowired;
@@ -20,7 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
*/
public abstract class DSpaceObjectConverter<M extends DSpaceObject, R extends org.dspace.app.rest.model
.DSpaceObjectRest>
extends DSpaceConverter<M, R> {
extends BrowsableDSpaceObjectConverter<M, R> {
@Autowired(required = true)
private MetadataConverter metadataConverter;
@@ -42,7 +43,7 @@ public abstract class DSpaceObjectConverter<M extends DSpaceObject, R extends or
return null;
}
public boolean supportsModel(DSpaceObject object) {
public boolean supportsModel(BrowsableObject object) {
return object != null && object.getClass().equals(getModelClass());
}

View File

@@ -0,0 +1,64 @@
/**
* 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/
*/
package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.PoolTaskRest;
import org.dspace.browse.BrowsableObject;
import org.dspace.xmlworkflow.storedcomponents.PoolTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* This is the converter from/to the PoolTask in the DSpace API data model
* and the REST data model
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class PoolTaskConverter
extends BrowsableDSpaceObjectConverter<PoolTask, org.dspace.app.rest.model.PoolTaskRest> {
@Autowired
private WorkflowItemConverter workflowItemConverter;
@Autowired
private EPersonConverter epersonConverter;
@Autowired
private GroupConverter groupConverter;
@Override
public PoolTaskRest fromModel(PoolTask obj) {
PoolTaskRest taskRest = new PoolTaskRest();
XmlWorkflowItem witem = obj.getWorkflowItem();
taskRest.setId(obj.getID());
taskRest.setWorkflowitem(workflowItemConverter.convert(witem));
if (obj.getEperson() != null) {
taskRest.setEperson(epersonConverter.convert(obj.getEperson()));
}
if (obj.getGroup() != null) {
taskRest.setGroup(groupConverter.convert(obj.getGroup()));
}
taskRest.setAction(obj.getActionID());
taskRest.setStep(obj.getStepID());
return taskRest;
}
@Override
public PoolTask toModel(PoolTaskRest obj) {
return null;
}
@Override
public boolean supportsModel(BrowsableObject object) {
return object instanceof PoolTask;
}
}

View File

@@ -0,0 +1,47 @@
/**
* 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/
*/
package org.dspace.app.rest.converter;
import org.dspace.app.rest.model.WorkflowItemRest;
import org.dspace.app.util.SubmissionConfigReaderException;
import org.dspace.browse.BrowsableObject;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.springframework.stereotype.Component;
/**
* This is the converter from/to the WorkflowItem in the DSpace API data model
* and the REST data model
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/
@Component
public class WorkflowItemConverter
extends AInprogressItemConverter<XmlWorkflowItem, org.dspace.app.rest.model.WorkflowItemRest, Integer> {
public WorkflowItemConverter() throws SubmissionConfigReaderException {
super();
}
@Override
public WorkflowItemRest fromModel(XmlWorkflowItem obj) {
WorkflowItemRest witem = new WorkflowItemRest();
fillFromModel(obj, witem);
return witem;
}
@Override
public XmlWorkflowItem toModel(WorkflowItemRest obj) {
return null;
}
@Override
public boolean supportsModel(BrowsableObject object) {
return object instanceof XmlWorkflowItem;
}
}

View File

@@ -7,24 +7,10 @@
*/
package org.dspace.app.rest.converter;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.app.rest.model.ErrorRest;
import org.dspace.app.rest.model.SubmissionDefinitionRest;
import org.dspace.app.rest.model.SubmissionSectionRest;
import org.dspace.app.rest.model.WorkspaceItemRest;
import org.dspace.app.rest.submit.AbstractRestProcessingStep;
import org.dspace.app.rest.submit.SubmissionService;
import org.dspace.app.util.SubmissionConfigReader;
import org.dspace.app.util.SubmissionConfigReaderException;
import org.dspace.app.util.SubmissionStepConfig;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.eperson.EPerson;
import org.springframework.beans.factory.annotation.Autowired;
import org.dspace.browse.BrowsableObject;
import org.dspace.content.WorkspaceItem;
import org.springframework.stereotype.Component;
/**
@@ -35,100 +21,17 @@ import org.springframework.stereotype.Component;
*/
@Component
public class WorkspaceItemConverter
extends DSpaceConverter<org.dspace.content.WorkspaceItem, org.dspace.app.rest.model.WorkspaceItemRest> {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(WorkspaceItemConverter.class);
@Autowired
private EPersonConverter epersonConverter;
@Autowired
private ItemConverter itemConverter;
@Autowired
private CollectionConverter collectionConverter;
private SubmissionConfigReader submissionConfigReader;
@Autowired
private SubmissionDefinitionConverter submissionDefinitionConverter;
@Autowired
private SubmissionSectionConverter submissionSectionConverter;
@Autowired
SubmissionService submissionService;
extends AInprogressItemConverter<WorkspaceItem, WorkspaceItemRest, Integer> {
public WorkspaceItemConverter() throws SubmissionConfigReaderException {
submissionConfigReader = new SubmissionConfigReader();
super();
}
@Override
public WorkspaceItemRest fromModel(org.dspace.content.WorkspaceItem obj) {
WorkspaceItemRest witem = new WorkspaceItemRest();
Collection collection = obj.getCollection();
Item item = obj.getItem();
EPerson submitter = null;
try {
submitter = obj.getSubmitter();
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
witem.setId(obj.getID());
witem.setCollection(collection != null ? collectionConverter.convert(collection) : null);
witem.setItem(itemConverter.convert(item));
witem.setSubmitter(epersonConverter.convert(submitter));
// 1. retrieve the submission definition
// 2. iterate over the submission section to allow to plugin additional
// info
if (collection != null) {
// we set the status to true as we will discover validation error later in this block
// we could eventually leave the status to empty if we don't have collection information, this could be
// eventually the case when projection support will be included
witem.setStatus(true);
SubmissionDefinitionRest def = submissionDefinitionConverter
.convert(submissionConfigReader.getSubmissionConfigByCollection(collection.getHandle()));
witem.setSubmissionDefinition(def);
for (SubmissionSectionRest sections : def.getPanels()) {
SubmissionStepConfig stepConfig = submissionSectionConverter.toModel(sections);
/*
* First, load the step processing class (using the current
* class loader)
*/
ClassLoader loader = this.getClass().getClassLoader();
Class stepClass;
try {
stepClass = loader.loadClass(stepConfig.getProcessingClassName());
Object stepInstance = stepClass.newInstance();
if (stepInstance instanceof AbstractRestProcessingStep) {
// load the interface for this step
AbstractRestProcessingStep stepProcessing =
(AbstractRestProcessingStep) stepClass.newInstance();
for (ErrorRest error : stepProcessing.validate(submissionService, obj, stepConfig)) {
addError(witem.getErrors(), error);
witem.setStatus(false);
}
witem.getSections()
.put(sections.getId(), stepProcessing.getData(submissionService, obj, stepConfig));
} else {
log.warn("The submission step class specified by '" + stepConfig.getProcessingClassName() +
"' does not extend the class org.dspace.app.rest.submit.AbstractRestProcessingStep!" +
" Therefore it cannot be used by the Configurable Submission as the " +
"<processing-class>!");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
fillFromModel(obj, witem);
return witem;
}
@@ -137,22 +40,8 @@ public class WorkspaceItemConverter
return null;
}
public void addError(List<ErrorRest> errors, ErrorRest toAdd) {
boolean found = false;
String i18nKey = toAdd.getMessage();
if (StringUtils.isNotBlank(i18nKey)) {
for (ErrorRest error : errors) {
if (i18nKey.equals(error.getMessage())) {
error.getPaths().addAll(toAdd.getPaths());
found = true;
break;
}
}
}
if (!found) {
errors.add(toAdd);
}
@Override
public boolean supportsModel(BrowsableObject object) {
return object instanceof WorkspaceItem;
}
}

View File

@@ -0,0 +1,93 @@
/**
* 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/
*/
package org.dspace.app.rest.model;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* Abstract class to share common aspects between the REST representation of inprogressSubmission
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*
* @param <T>
* the serializable class used as primary key
*/
public abstract class AInprogressSubmissionRest<T extends Serializable> extends BaseObjectRest<T> {
private Date lastModified = new Date();
private Map<String, Serializable> sections;
@JsonIgnore
private CollectionRest collection;
@JsonIgnore
private ItemRest item;
@JsonIgnore
private SubmissionDefinitionRest submissionDefinition;
@JsonIgnore
private EPersonRest submitter;
public AInprogressSubmissionRest() {
super();
}
public Date getLastModified() {
return lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
public ItemRest getItem() {
return item;
}
public void setItem(ItemRest item) {
this.item = item;
}
public SubmissionDefinitionRest getSubmissionDefinition() {
return submissionDefinition;
}
public void setSubmissionDefinition(SubmissionDefinitionRest submissionDefinition) {
this.submissionDefinition = submissionDefinition;
}
public EPersonRest getSubmitter() {
return submitter;
}
public void setSubmitter(EPersonRest submitter) {
this.submitter = submitter;
}
public Map<String, Serializable> getSections() {
if (sections == null) {
sections = new HashMap<String, Serializable>();
}
return sections;
}
public void setSections(Map<String, Serializable> sections) {
this.sections = sections;
}
public CollectionRest getCollection() {
return collection;
}
public void setCollection(CollectionRest collection) {
this.collection = collection;
}
}

View File

@@ -28,13 +28,6 @@ public abstract class BaseObjectRest<T extends Serializable> implements Identifi
@JsonInclude(Include.NON_EMPTY)
private List<ErrorRest> errors;
private Boolean status;
@JsonInclude(Include.NON_NULL)
public Boolean isStatus() {
return status;
}
@Override
public T getId() {
return id;
@@ -55,7 +48,4 @@ public abstract class BaseObjectRest<T extends Serializable> implements Identifi
this.errors = errors;
}
public void setStatus(Boolean status) {
this.status = status;
}
}

View File

@@ -0,0 +1,95 @@
/**
* 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/
*/
package org.dspace.app.rest.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.dspace.app.rest.RestResourceController;
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
/**
* The ClaimedTask REST Resource
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
public class ClaimedTaskRest extends BaseObjectRest<Integer> {
public static final String NAME = "claimedtask";
public static final String CATEGORY = RestAddressableModel.WORKFLOW;
private String step;
private String action;
@JsonIgnore
private EPersonRest owner;
@JsonIgnore
private WorkflowItemRest workflowitem;
@Override
public String getCategory() {
return CATEGORY;
}
@Override
public String getType() {
return NAME;
}
@Override
public Class getController() {
return RestResourceController.class;
}
/**
* @see ClaimedTask#getStepID()
* @return the step
*/
public String getStep() {
return step;
}
public void setStep(String step) {
this.step = step;
}
/**
* @see ClaimedTaskRest#getAction()
* @return the action
*/
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
/**
* @see ClaimedTaskRest#getOwner()
* @return the owner of the task
*/
public EPersonRest getOwner() {
return owner;
}
public void setOwner(EPersonRest owner) {
this.owner = owner;
}
/**
*
* @return the WorkflowItemRest that belong to this claimed task
*/
public WorkflowItemRest getWorkflowitem() {
return workflowitem;
}
public void setWorkflowitem(WorkflowItemRest workflowitem) {
this.workflowitem = workflowitem;
}
}

View File

@@ -0,0 +1,110 @@
/**
* 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/
*/
package org.dspace.app.rest.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.dspace.app.rest.RestResourceController;
import org.dspace.xmlworkflow.storedcomponents.PoolTask;
/**
* The PoolTask REST Resource
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
public class PoolTaskRest extends BaseObjectRest<Integer> {
public static final String NAME = "pooltask";
public static final String CATEGORY = RestAddressableModel.WORKFLOW;
private String step;
private String action;
@JsonIgnore
private EPersonRest eperson;
@JsonIgnore
private GroupRest group;
@JsonIgnore
private WorkflowItemRest workflowitem;
@Override
public String getCategory() {
return CATEGORY;
}
@Override
public String getType() {
return NAME;
}
@Override
public Class getController() {
return RestResourceController.class;
}
/**
* @see PoolTask#getStepID()
* @return
*/
public String getStep() {
return step;
}
public void setStep(String step) {
this.step = step;
}
/**
* @see PoolTask#getActionID()
* @return
*/
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
/**
* @see PoolTask#getEperson()
* @return
*/
public EPersonRest getEperson() {
return eperson;
}
public void setEperson(EPersonRest eperson) {
this.eperson = eperson;
}
/**
* @see PoolTask#getGroup()
* @return
*/
public GroupRest getGroup() {
return group;
}
public void setGroup(GroupRest group) {
this.group = group;
}
/**
*
* @return the WorkflowItemRest that belong to this pool task
*/
public WorkflowItemRest getWorkflowitem() {
return workflowitem;
}
public void setWorkflowitem(WorkflowItemRest workflowitem) {
this.workflowitem = workflowitem;
}
}

View File

@@ -27,6 +27,7 @@ public interface RestModel extends Serializable {
public static final String CONFIGURATION = "config";
public static final String INTEGRATION = "integration";
public static final String SUBMISSION = "submission";
public static final String WORKFLOW = "workflow";
public static final String AUTHORIZATION = "authz";
public String getType();

View File

@@ -0,0 +1,35 @@
/**
* 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/
*/
package org.dspace.app.rest.model;
import org.dspace.app.rest.RestResourceController;
/**
* The WorkflowItem REST Resource
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
public class WorkflowItemRest extends AInprogressSubmissionRest<Integer> {
public static final String NAME = "workflowitem";
public static final String CATEGORY = RestAddressableModel.WORKFLOW;
@Override
public String getCategory() {
return CATEGORY;
}
@Override
public String getType() {
return NAME;
}
@Override
public Class getController() {
return RestResourceController.class;
}
}

View File

@@ -7,12 +7,6 @@
*/
package org.dspace.app.rest.model;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.dspace.app.rest.RestResourceController;
/**
@@ -20,26 +14,10 @@ import org.dspace.app.rest.RestResourceController;
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
public class WorkspaceItemRest extends BaseObjectRest<Integer> {
public class WorkspaceItemRest extends AInprogressSubmissionRest<Integer> {
public static final String NAME = "workspaceitem";
public static final String CATEGORY = RestAddressableModel.SUBMISSION;
private Date lastModified = new Date();
private Map<String, Serializable> sections;
@JsonIgnore
private CollectionRest collection;
@JsonIgnore
private ItemRest item;
@JsonIgnore
private SubmissionDefinitionRest submissionDefinition;
@JsonIgnore
private EPersonRest submitter;
@Override
public String getCategory() {
return CATEGORY;
@@ -50,59 +28,8 @@ public class WorkspaceItemRest extends BaseObjectRest<Integer> {
return NAME;
}
public Date getLastModified() {
return lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
public ItemRest getItem() {
return item;
}
public void setItem(ItemRest item) {
this.item = item;
}
public SubmissionDefinitionRest getSubmissionDefinition() {
return submissionDefinition;
}
public void setSubmissionDefinition(SubmissionDefinitionRest submissionDefinition) {
this.submissionDefinition = submissionDefinition;
}
public EPersonRest getSubmitter() {
return submitter;
}
public void setSubmitter(EPersonRest submitter) {
this.submitter = submitter;
}
@Override
public Class getController() {
return RestResourceController.class;
}
public Map<String, Serializable> getSections() {
if (sections == null) {
sections = new HashMap<String, Serializable>();
}
return sections;
}
public void setSections(Map<String, Serializable> sections) {
this.sections = sections;
}
public CollectionRest getCollection() {
return collection;
}
public void setCollection(CollectionRest collection) {
this.collection = collection;
}
}

View File

@@ -0,0 +1,25 @@
/**
* 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/
*/
package org.dspace.app.rest.model.hateoas;
import org.dspace.app.rest.model.ClaimedTaskRest;
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
import org.dspace.app.rest.utils.Utils;
/**
* ClaimedTask Rest HAL Resource. The HAL Resource wraps the REST Resource
* adding support for the links and embedded resources
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@RelNameDSpaceResource(ClaimedTaskRest.NAME)
public class ClaimedTaskResource extends DSpaceResource<ClaimedTaskRest> {
public ClaimedTaskResource(ClaimedTaskRest witem, Utils utils, String... rels) {
super(witem, utils, rels);
}
}

View File

@@ -0,0 +1,25 @@
/**
* 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/
*/
package org.dspace.app.rest.model.hateoas;
import org.dspace.app.rest.model.PoolTaskRest;
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
import org.dspace.app.rest.utils.Utils;
/**
* PooledTask Rest HAL Resource. The HAL Resource wraps the REST Resource
* adding support for the links and embedded resources
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@RelNameDSpaceResource(PoolTaskRest.NAME)
public class PoolTaskResource extends DSpaceResource<PoolTaskRest> {
public PoolTaskResource(PoolTaskRest witem, Utils utils, String... rels) {
super(witem, utils, rels);
}
}

View File

@@ -0,0 +1,25 @@
/**
* 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/
*/
package org.dspace.app.rest.model.hateoas;
import org.dspace.app.rest.model.WorkflowItemRest;
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
import org.dspace.app.rest.utils.Utils;
/**
* WorkflowItem Rest HAL Resource. The HAL Resource wraps the REST Resource
* adding support for the links and embedded resources
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@RelNameDSpaceResource(WorkflowItemRest.NAME)
public class WorkflowItemResource extends DSpaceResource<WorkflowItemRest> {
public WorkflowItemResource(WorkflowItemRest witem, Utils utils, String... rels) {
super(witem, utils, rels);
}
}

View File

@@ -11,7 +11,6 @@ import javax.annotation.Nonnull;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.rest.webmvc.json.patch.LateObjectEvaluator;
import org.springframework.data.rest.webmvc.json.patch.PatchException;
/**

View File

@@ -0,0 +1,23 @@
/**
* 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/
*/
package org.dspace.app.rest.model.patch;
/**
* <p>
* Strategy interface for resolving values from an operation definition.
* </p>
*
* Based on {@link org.springframework.data.rest.webmvc.json.patch.LateObjectEvaluator}
*
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/
public interface LateObjectEvaluator {
<T> Object evaluate(Class<T> type);
}

View File

@@ -0,0 +1,198 @@
/**
* 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/
*/
package org.dspace.app.rest.repository;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.converter.ClaimedTaskConverter;
import org.dspace.app.rest.exception.RESTAuthorizationException;
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.ClaimedTaskRest;
import org.dspace.app.rest.model.PoolTaskRest;
import org.dspace.app.rest.model.hateoas.ClaimedTaskResource;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.service.EPersonService;
import org.dspace.workflow.WorkflowException;
import org.dspace.xmlworkflow.WorkflowConfigurationException;
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
import org.dspace.xmlworkflow.service.WorkflowRequirementsService;
import org.dspace.xmlworkflow.service.XmlWorkflowService;
import org.dspace.xmlworkflow.state.Step;
import org.dspace.xmlworkflow.state.Workflow;
import org.dspace.xmlworkflow.state.actions.Action;
import org.dspace.xmlworkflow.state.actions.WorkflowActionConfig;
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
* This is the repository responsible to manage PooledTask Rest object
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component(PoolTaskRest.CATEGORY + "." + ClaimedTaskRest.NAME)
public class ClaimedTaskRestRepository extends DSpaceRestRepository<ClaimedTaskRest, Integer> {
private static final Logger log = Logger.getLogger(ClaimedTaskRestRepository.class);
@Autowired
ItemService itemService;
@Autowired
EPersonService epersonService;
@Autowired
ClaimedTaskService claimedTaskService;
@Autowired
ClaimedTaskConverter converter;
@Autowired
XmlWorkflowService workflowService;
@Autowired
WorkflowRequirementsService workflowRequirementsService;
@Autowired
AuthorizeService authorizeService;
@Override
@PreAuthorize("hasPermission(#id, 'CLAIMEDTASK', 'READ')")
public ClaimedTaskRest findOne(Context context, Integer id) {
ClaimedTask task = null;
try {
task = claimedTaskService.find(context, id);
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
if (task == null) {
return null;
}
return converter.fromModel(task);
}
@SearchRestMethod(name = "findByUser")
public Page<ClaimedTaskRest> findByUser(@Parameter(value = "uuid", required = true) UUID userID,
Pageable pageable) {
//FIXME this should be secured with annotation but they are currently ignored by search methods
List<ClaimedTask> tasks = null;
try {
Context context = obtainContext();
EPerson currentUser = context.getCurrentUser();
if (currentUser == null) {
throw new RESTAuthorizationException(
"This endpoint is available only to logged-in user to search for their"
+ " own claimed tasks or the admins");
}
if (authorizeService.isAdmin(context) || userID.equals(currentUser.getID())) {
EPerson ep = epersonService.find(context, userID);
tasks = claimedTaskService.findByEperson(context, ep);
} else {
throw new RESTAuthorizationException("Only administrators can search for claimed tasks of other users");
}
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
Page<ClaimedTaskRest> page = utils.getPage(tasks, pageable).map(converter);
return page;
}
@Override
public Class<ClaimedTaskRest> getDomainClass() {
return ClaimedTaskRest.class;
}
@Override
public ClaimedTaskResource wrapResource(ClaimedTaskRest task, String... rels) {
return new ClaimedTaskResource(task, utils, rels);
}
@Override
@PreAuthorize("hasPermission(#id, 'CLAIMEDTASK', 'WRITE')")
protected ClaimedTaskRest action(Context context, HttpServletRequest request, Integer id)
throws SQLException, IOException {
ClaimedTask task = null;
task = claimedTaskService.find(context, id);
if (task == null) {
throw new ResourceNotFoundException("ClaimedTask ID " + id + " not found");
}
XmlWorkflowServiceFactory factory = (XmlWorkflowServiceFactory) XmlWorkflowServiceFactory.getInstance();
Workflow workflow;
try {
workflow = factory.getWorkflowFactory().getWorkflow(task.getWorkflowItem().getCollection());
Step step = workflow.getStep(task.getStepID());
WorkflowActionConfig currentActionConfig = step.getActionConfig(task.getActionID());
workflowService
.doState(context, context.getCurrentUser(), request, task.getWorkflowItem().getID(), workflow,
currentActionConfig);
if (!Action.getErrorFields(request).isEmpty()) {
throw new UnprocessableEntityException(
"Missing required fields: " + StringUtils.join(Action.getErrorFields(request), ","));
}
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (WorkflowException e) {
throw new UnprocessableEntityException(
"Invalid workflow action: " + e.getMessage(), e);
} catch (WorkflowConfigurationException | MessagingException e) {
throw new RuntimeException(e.getMessage(), e);
}
return null;
}
@Override
/**
* This method delete only the claimed task. The workflow engine will return it to the pool if there are not
* enough other claimed tasks for the same workflowitem.
*
*/
@PreAuthorize("hasPermission(#id, 'CLAIMEDTASK', 'DELETE')")
protected void delete(Context context, Integer id) {
ClaimedTask task = null;
try {
task = claimedTaskService.find(context, id);
if (task == null) {
throw new ResourceNotFoundException("ClaimedTask ID " + id + " not found");
}
XmlWorkflowItem workflowItem = task.getWorkflowItem();
workflowService.deleteClaimedTask(context, workflowItem, task);
workflowRequirementsService.removeClaimedUser(context, workflowItem, task.getOwner(), task.getStepID());
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (SQLException | IOException | WorkflowConfigurationException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public Page<ClaimedTaskRest> findAll(Context context, Pageable pageable) {
throw new RepositoryMethodNotImplementedException(ClaimedTaskRest.NAME, "findAll");
}
}

View File

@@ -413,6 +413,18 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
throw new RepositoryMethodNotImplementedException(apiCategory, model);
}
public T action(HttpServletRequest request, ID id) throws SQLException, IOException {
Context context = obtainContext();
T entity = action(context, request, id);
context.commit();
return entity;
}
protected T action(Context context, HttpServletRequest request, ID id)
throws SQLException, IOException {
throw new RuntimeException("No implementation found; Method not allowed!");
}
/**
* Bulk create object instances from an uploaded file
*

View File

@@ -0,0 +1,158 @@
/**
* 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/
*/
package org.dspace.app.rest.repository;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.converter.PoolTaskConverter;
import org.dspace.app.rest.exception.RESTAuthorizationException;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.PoolTaskRest;
import org.dspace.app.rest.model.hateoas.PoolTaskResource;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.service.EPersonService;
import org.dspace.workflow.WorkflowException;
import org.dspace.xmlworkflow.WorkflowConfigurationException;
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
import org.dspace.xmlworkflow.service.WorkflowRequirementsService;
import org.dspace.xmlworkflow.service.XmlWorkflowService;
import org.dspace.xmlworkflow.state.Step;
import org.dspace.xmlworkflow.state.Workflow;
import org.dspace.xmlworkflow.state.actions.WorkflowActionConfig;
import org.dspace.xmlworkflow.storedcomponents.PoolTask;
import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
* This is the repository responsible to manage PooledTask Rest object
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component(PoolTaskRest.CATEGORY + "." + PoolTaskRest.NAME)
public class PoolTaskRestRepository extends DSpaceRestRepository<PoolTaskRest, Integer> {
private static final Logger log = Logger.getLogger(PoolTaskRestRepository.class);
@Autowired
ItemService itemService;
@Autowired
EPersonService epersonService;
@Autowired
PoolTaskService poolTaskService;
@Autowired
PoolTaskConverter converter;
@Autowired
XmlWorkflowService workflowService;
@Autowired
WorkflowRequirementsService workflowRequirementsService;
@Autowired
AuthorizeService authorizeService;
@Override
@PreAuthorize("hasPermission(#id, 'POOLTASK', 'READ')")
public PoolTaskRest findOne(Context context, Integer id) {
PoolTask task = null;
try {
task = poolTaskService.find(context, id);
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
if (task == null) {
return null;
}
return converter.fromModel(task);
}
@SearchRestMethod(name = "findByUser")
public Page<PoolTaskRest> findByUser(@Parameter(value = "uuid") UUID userID, Pageable pageable) {
List<PoolTask> tasks = null;
try {
Context context = obtainContext();
//FIXME this should be secured with annotation but they are currently ignored by search methods
EPerson currentUser = context.getCurrentUser();
if (currentUser == null) {
throw new RESTAuthorizationException(
"This endpoint is available only to logged-in user"
+ " to search for their own pool tasks or the admins");
}
if (authorizeService.isAdmin(context) || userID.equals(currentUser.getID())) {
EPerson ep = epersonService.find(context, userID);
tasks = poolTaskService.findByEperson(context, ep);
} else {
throw new RESTAuthorizationException("Only administrators can search for pool tasks of other users");
}
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (SQLException | IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
Page<PoolTaskRest> page = utils.getPage(tasks, pageable).map(converter);
return page;
}
@Override
public Class<PoolTaskRest> getDomainClass() {
return PoolTaskRest.class;
}
@Override
public PoolTaskResource wrapResource(PoolTaskRest task, String... rels) {
return new PoolTaskResource(task, utils, rels);
}
@Override
@PreAuthorize("hasPermission(#id, 'POOLTASK', 'WRITE')")
protected PoolTaskRest action(Context context, HttpServletRequest request, Integer id)
throws SQLException, IOException {
PoolTask task = null;
try {
task = poolTaskService.find(context, id);
XmlWorkflowServiceFactory factory = (XmlWorkflowServiceFactory) XmlWorkflowServiceFactory.getInstance();
Workflow workflow = factory.getWorkflowFactory().getWorkflow(task.getWorkflowItem().getCollection());
Step step = workflow.getStep(task.getStepID());
WorkflowActionConfig currentActionConfig = step.getActionConfig(task.getActionID());
workflowService
.doState(context, context.getCurrentUser(), request, task.getWorkflowItem().getID(), workflow,
currentActionConfig);
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (WorkflowConfigurationException | MessagingException | WorkflowException e) {
throw new UnprocessableEntityException(e.getMessage(), e);
}
return null;
}
@Override
public Page<PoolTaskRest> findAll(Context context, Pageable pageable) {
throw new RuntimeException("Method not allowed!");
}
}

View File

@@ -0,0 +1,305 @@
/**
* 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/
*/
package org.dspace.app.rest.repository;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.converter.WorkflowItemConverter;
import org.dspace.app.rest.exception.PatchBadRequestException;
import org.dspace.app.rest.exception.RESTAuthorizationException;
import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.ErrorRest;
import org.dspace.app.rest.model.WorkflowItemRest;
import org.dspace.app.rest.model.hateoas.WorkflowItemResource;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.model.patch.Patch;
import org.dspace.app.rest.submit.AbstractRestProcessingStep;
import org.dspace.app.rest.submit.SubmissionService;
import org.dspace.app.rest.submit.UploadableStep;
import org.dspace.app.util.SubmissionConfig;
import org.dspace.app.util.SubmissionConfigReader;
import org.dspace.app.util.SubmissionConfigReaderException;
import org.dspace.app.util.SubmissionStepConfig;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.service.BitstreamFormatService;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.EPersonServiceImpl;
import org.dspace.services.ConfigurationService;
import org.dspace.workflow.WorkflowException;
import org.dspace.workflow.WorkflowService;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
/**
* This is the repository responsible to manage WorkflowItem Rest object
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component(WorkflowItemRest.CATEGORY + "." + WorkflowItemRest.NAME)
public class WorkflowItemRestRepository extends DSpaceRestRepository<WorkflowItemRest, Integer> {
public static final String OPERATION_PATH_SECTIONS = "sections";
private static final Logger log = Logger.getLogger(WorkflowItemRestRepository.class);
@Autowired
XmlWorkflowItemService wis;
@Autowired
ItemService itemService;
@Autowired
BitstreamService bitstreamService;
@Autowired
BitstreamFormatService bitstreamFormatService;
@Autowired
ConfigurationService configurationService;
@Autowired
WorkflowItemConverter converter;
@Autowired
SubmissionService submissionService;
@Autowired
EPersonServiceImpl epersonService;
@Autowired
WorkflowService<XmlWorkflowItem> wfs;
private SubmissionConfigReader submissionConfigReader;
public WorkflowItemRestRepository() throws SubmissionConfigReaderException {
submissionConfigReader = new SubmissionConfigReader();
}
@Override
@PreAuthorize("hasPermission(#id, 'WORKFLOWITEM', 'READ')")
public WorkflowItemRest findOne(Context context, Integer id) {
XmlWorkflowItem witem = null;
try {
witem = wis.find(context, id);
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
if (witem == null) {
return null;
}
return converter.fromModel(witem);
}
@Override
@PreAuthorize("hasAuthority('ADMIN')")
public Page<WorkflowItemRest> findAll(Context context, Pageable pageable) {
List<XmlWorkflowItem> witems = null;
int total = 0;
try {
total = wis.countAll(context);
witems = wis.findAll(context, pageable.getPageNumber(), pageable.getPageSize());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
Page<WorkflowItemRest> page = new PageImpl<XmlWorkflowItem>(witems, pageable, total).map(converter);
return page;
}
@SearchRestMethod(name = "findBySubmitter")
@PreAuthorize("hasAuthority('ADMIN')")
public Page<WorkflowItemRest> findBySubmitter(@Parameter(value = "uuid") UUID submitterID, Pageable pageable) {
List<XmlWorkflowItem> witems = null;
int total = 0;
try {
Context context = obtainContext();
EPerson ep = epersonService.find(context, submitterID);
witems = wis.findBySubmitter(context, ep, pageable.getPageNumber(), pageable.getPageSize());
total = wis.countBySubmitter(context, ep);
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
Page<WorkflowItemRest> page = new PageImpl<XmlWorkflowItem>(witems, pageable, total).map(converter);
return page;
}
@Override
protected WorkflowItemRest createAndReturn(Context context) {
XmlWorkflowItem source;
try {
source = submissionService.createWorkflowItem(context, getRequestService().getCurrentRequest());
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (WorkflowException e) {
throw new UnprocessableEntityException(
"Invalid workflow action: " + e.getMessage(), e);
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
//if the item go directly in published status we have to manage a status code 204 with no content
if (source.getItem().isArchived()) {
return null;
}
return converter.convert(source);
}
@Override
public Class<WorkflowItemRest> getDomainClass() {
return WorkflowItemRest.class;
}
@Override
public WorkflowItemResource wrapResource(WorkflowItemRest witem, String... rels) {
return new WorkflowItemResource(witem, utils, rels);
}
@Override
public WorkflowItemRest upload(HttpServletRequest request, String apiCategory, String model, Integer id,
MultipartFile file) throws Exception {
Context context = obtainContext();
WorkflowItemRest wsi = findOne(id);
XmlWorkflowItem source = wis.find(context, id);
List<ErrorRest> errors = new ArrayList<ErrorRest>();
SubmissionConfig submissionConfig =
submissionConfigReader.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
for (int i = 0; i < submissionConfig.getNumberOfSteps(); i++) {
SubmissionStepConfig stepConfig = submissionConfig.getStep(i);
/*
* First, load the step processing class (using the current
* class loader)
*/
ClassLoader loader = this.getClass().getClassLoader();
Class stepClass;
try {
stepClass = loader.loadClass(stepConfig.getProcessingClassName());
Object stepInstance = stepClass.newInstance();
if (UploadableStep.class.isAssignableFrom(stepClass)) {
UploadableStep uploadableStep = (UploadableStep) stepInstance;
uploadableStep.doPreProcessing(context, source);
ErrorRest err =
uploadableStep.upload(context, submissionService, stepConfig, source, file);
uploadableStep.doPostProcessing(context, source);
if (err != null) {
errors.add(err);
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
wsi = converter.convert(source);
if (!errors.isEmpty()) {
wsi.getErrors().addAll(errors);
}
context.commit();
return wsi;
}
@Override
public void patch(Context context, HttpServletRequest request, String apiCategory, String model, Integer id,
Patch patch) throws SQLException, AuthorizeException {
List<Operation> operations = patch.getOperations();
WorkflowItemRest wsi = findOne(id);
XmlWorkflowItem source = wis.find(context, id);
for (Operation op : operations) {
//the value in the position 0 is a null value
String[] path = op.getPath().substring(1).split("/", 3);
if (OPERATION_PATH_SECTIONS.equals(path[0])) {
String section = path[1];
evaluatePatch(context, request, source, wsi, section, op);
} else {
throw new PatchBadRequestException(
"Patch path operation need to starts with '" + OPERATION_PATH_SECTIONS + "'");
}
}
wis.update(context, source);
}
private void evaluatePatch(Context context, HttpServletRequest request, XmlWorkflowItem source,
WorkflowItemRest wsi, String section, Operation op) {
SubmissionConfig submissionConfig =
submissionConfigReader.getSubmissionConfigByName(wsi.getSubmissionDefinition().getName());
for (int stepNum = 0; stepNum < submissionConfig.getNumberOfSteps(); stepNum++) {
SubmissionStepConfig stepConfig = submissionConfig.getStep(stepNum);
if (section.equals(stepConfig.getId())) {
/*
* First, load the step processing class (using the current
* class loader)
*/
ClassLoader loader = this.getClass().getClassLoader();
Class stepClass;
try {
stepClass = loader.loadClass(stepConfig.getProcessingClassName());
Object stepInstance = stepClass.newInstance();
if (stepInstance instanceof AbstractRestProcessingStep) {
// load the JSPStep interface for this step
AbstractRestProcessingStep stepProcessing =
(AbstractRestProcessingStep) stepClass.newInstance();
stepProcessing.doPreProcessing(context, source);
stepProcessing.doPatchProcessing(context, getRequestService().getCurrentRequest(), source, op);
stepProcessing.doPostProcessing(context, source);
} else {
throw new PatchBadRequestException(
"The submission step class specified by '" + stepConfig.getProcessingClassName() +
"' does not extend the class org.dspace.submit.AbstractProcessingStep!" +
" Therefore it cannot be used by the Configurable Submission as the <processing-class>!");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
}
@Override
/**
* This method provides support for the administrative abort workflow functionality. The abort functionality will
* move the workflowitem back to the submitter workspace regardless to how the workflow is designed
*/
protected void delete(Context context, Integer id) {
XmlWorkflowItem witem = null;
try {
witem = wis.find(context, id);
if (witem == null) {
throw new ResourceNotFoundException("WorkflowItem ID " + id + " not found");
}
wfs.abort(context, witem, context.getCurrentUser());
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (SQLException | IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}

Some files were not shown because too many files have changed in this diff Show More