mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-15 05:53:08 +00:00
Merge branch 'main' into w2p-99200_request-copy-bugfix
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* 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.alerts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum representing the options for allowing sessions:
|
||||||
|
* ALLOW_ALL_SESSIONS - Will allow all users to log in and continue their sessions
|
||||||
|
* ALLOW_CURRENT_SESSIONS_ONLY - Will prevent non admin users from logging in, however logged-in users
|
||||||
|
* will remain logged in
|
||||||
|
* ALLOW_ADMIN_SESSIONS_ONLY - Only admin users can log in, non admin sessions will be interrupted
|
||||||
|
*
|
||||||
|
* NOTE: This functionality can be stored in the database, but no support is present right now to interrupt and prevent
|
||||||
|
* sessions.
|
||||||
|
*/
|
||||||
|
public enum AllowSessionsEnum {
|
||||||
|
ALLOW_ALL_SESSIONS("all"),
|
||||||
|
ALLOW_CURRENT_SESSIONS_ONLY("current"),
|
||||||
|
ALLOW_ADMIN_SESSIONS_ONLY("admin");
|
||||||
|
|
||||||
|
private String allowSessionsType;
|
||||||
|
|
||||||
|
AllowSessionsEnum(String allowSessionsType) {
|
||||||
|
this.allowSessionsType = allowSessionsType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return allowSessionsType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AllowSessionsEnum fromString(String alertAllowSessionType) {
|
||||||
|
if (alertAllowSessionType == null) {
|
||||||
|
return AllowSessionsEnum.ALLOW_ALL_SESSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (alertAllowSessionType) {
|
||||||
|
case "all":
|
||||||
|
return AllowSessionsEnum.ALLOW_ALL_SESSIONS;
|
||||||
|
case "current":
|
||||||
|
return AllowSessionsEnum.ALLOW_CURRENT_SESSIONS_ONLY;
|
||||||
|
case "admin" :
|
||||||
|
return AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("No corresponding enum value for provided string: "
|
||||||
|
+ alertAllowSessionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
179
dspace-api/src/main/java/org/dspace/alerts/SystemWideAlert.java
Normal file
179
dspace-api/src/main/java/org/dspace/alerts/SystemWideAlert.java
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
* 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.alerts;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import javax.persistence.Cacheable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.SequenceGenerator;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Temporal;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
import org.dspace.core.ReloadableEntity;
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database object representing system-wide alerts
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Cacheable
|
||||||
|
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy")
|
||||||
|
@Table(name = "systemwidealert")
|
||||||
|
public class SystemWideAlert implements ReloadableEntity<Integer> {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "alert_id_seq")
|
||||||
|
@SequenceGenerator(name = "alert_id_seq", sequenceName = "alert_id_seq", allocationSize = 1)
|
||||||
|
@Column(name = "alert_id", unique = true, nullable = false)
|
||||||
|
private Integer alertId;
|
||||||
|
|
||||||
|
@Column(name = "message", nullable = false)
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
@Column(name = "allow_sessions")
|
||||||
|
private String allowSessions;
|
||||||
|
|
||||||
|
@Column(name = "countdown_to")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date countdownTo;
|
||||||
|
|
||||||
|
@Column(name = "active")
|
||||||
|
private boolean active;
|
||||||
|
|
||||||
|
protected SystemWideAlert() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the ID that the system-wide alert holds within the database
|
||||||
|
*
|
||||||
|
* @return The ID that the system-wide alert holds within the database
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Integer getID() {
|
||||||
|
return alertId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the ID for the system-wide alert
|
||||||
|
*
|
||||||
|
* @param alertID The ID to set
|
||||||
|
*/
|
||||||
|
public void setID(final Integer alertID) {
|
||||||
|
this.alertId = alertID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the message of the system-wide alert
|
||||||
|
*
|
||||||
|
* @return the message of the system-wide alert
|
||||||
|
*/
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the message of the system-wide alert
|
||||||
|
*
|
||||||
|
* @param message The message to set
|
||||||
|
*/
|
||||||
|
public void setMessage(final String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve what kind of sessions are allowed while the system-wide alert is active
|
||||||
|
*
|
||||||
|
* @return what kind of sessions are allowed while the system-wide alert is active
|
||||||
|
*/
|
||||||
|
public AllowSessionsEnum getAllowSessions() {
|
||||||
|
return AllowSessionsEnum.fromString(allowSessions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set what kind of sessions are allowed while the system-wide alert is active
|
||||||
|
*
|
||||||
|
* @param allowSessions Integer representing what kind of sessions are allowed
|
||||||
|
*/
|
||||||
|
public void setAllowSessions(AllowSessionsEnum allowSessions) {
|
||||||
|
this.allowSessions = allowSessions.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the date to which will be count down when the system-wide alert is active
|
||||||
|
*
|
||||||
|
* @return the date to which will be count down when the system-wide alert is active
|
||||||
|
*/
|
||||||
|
public Date getCountdownTo() {
|
||||||
|
return countdownTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the date to which will be count down when the system-wide alert is active
|
||||||
|
*
|
||||||
|
* @param countdownTo The date to which will be count down
|
||||||
|
*/
|
||||||
|
public void setCountdownTo(final Date countdownTo) {
|
||||||
|
this.countdownTo = countdownTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve whether the system-wide alert is active
|
||||||
|
*
|
||||||
|
* @return whether the system-wide alert is active
|
||||||
|
*/
|
||||||
|
public boolean isActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether the system-wide alert is active
|
||||||
|
*
|
||||||
|
* @param active Whether the system-wide alert is active
|
||||||
|
*/
|
||||||
|
public void setActive(final boolean active) {
|
||||||
|
this.active = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <code>true</code> if <code>other</code> is the same SystemWideAlert
|
||||||
|
* as this object, <code>false</code> otherwise
|
||||||
|
*
|
||||||
|
* @param other object to compare to
|
||||||
|
* @return <code>true</code> if object passed in represents the same
|
||||||
|
* system-wide alert as this object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
return (other instanceof SystemWideAlert &&
|
||||||
|
new EqualsBuilder().append(this.getID(), ((SystemWideAlert) other).getID())
|
||||||
|
.append(this.getMessage(), ((SystemWideAlert) other).getMessage())
|
||||||
|
.append(this.getAllowSessions(), ((SystemWideAlert) other).getAllowSessions())
|
||||||
|
.append(this.getCountdownTo(), ((SystemWideAlert) other).getCountdownTo())
|
||||||
|
.append(this.isActive(), ((SystemWideAlert) other).isActive())
|
||||||
|
.isEquals());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return new HashCodeBuilder(17, 37)
|
||||||
|
.append(this.getID())
|
||||||
|
.append(this.getMessage())
|
||||||
|
.append(this.getAllowSessions())
|
||||||
|
.append(this.getCountdownTo())
|
||||||
|
.append(this.isActive())
|
||||||
|
.toHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* 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.alerts;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.alerts.dao.SystemWideAlertDAO;
|
||||||
|
import org.dspace.alerts.service.SystemWideAlertService;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.core.LogHelper;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The implementation for the {@link SystemWideAlertService} class
|
||||||
|
*/
|
||||||
|
public class SystemWideAlertServiceImpl implements SystemWideAlertService {
|
||||||
|
|
||||||
|
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SystemWideAlertService.class);
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SystemWideAlertDAO systemWideAlertDAO;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SystemWideAlert create(final Context context, final String message,
|
||||||
|
final AllowSessionsEnum allowSessionsType,
|
||||||
|
final Date countdownTo, final boolean active) throws SQLException,
|
||||||
|
AuthorizeException {
|
||||||
|
if (!authorizeService.isAdmin(context)) {
|
||||||
|
throw new AuthorizeException(
|
||||||
|
"Only administrators can create a system-wide alert");
|
||||||
|
}
|
||||||
|
SystemWideAlert systemWideAlert = new SystemWideAlert();
|
||||||
|
systemWideAlert.setMessage(message);
|
||||||
|
systemWideAlert.setAllowSessions(allowSessionsType);
|
||||||
|
systemWideAlert.setCountdownTo(countdownTo);
|
||||||
|
systemWideAlert.setActive(active);
|
||||||
|
|
||||||
|
SystemWideAlert createdAlert = systemWideAlertDAO.create(context, systemWideAlert);
|
||||||
|
log.info(LogHelper.getHeader(context, "system_wide_alert_create",
|
||||||
|
"System Wide Alert has been created with message: '" + message + "' and ID "
|
||||||
|
+ createdAlert.getID() + " and allowSessionsType " + allowSessionsType +
|
||||||
|
" and active set to " + active));
|
||||||
|
|
||||||
|
|
||||||
|
return createdAlert;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SystemWideAlert find(final Context context, final int alertId) throws SQLException {
|
||||||
|
return systemWideAlertDAO.findByID(context, SystemWideAlert.class, alertId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SystemWideAlert> findAll(final Context context) throws SQLException {
|
||||||
|
return systemWideAlertDAO.findAll(context, SystemWideAlert.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SystemWideAlert> findAll(final Context context, final int limit, final int offset) throws SQLException {
|
||||||
|
return systemWideAlertDAO.findAll(context, limit, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SystemWideAlert> findAllActive(final Context context, final int limit, final int offset)
|
||||||
|
throws SQLException {
|
||||||
|
return systemWideAlertDAO.findAllActive(context, limit, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(final Context context, final SystemWideAlert systemWideAlert)
|
||||||
|
throws SQLException, IOException, AuthorizeException {
|
||||||
|
if (!authorizeService.isAdmin(context)) {
|
||||||
|
throw new AuthorizeException(
|
||||||
|
"Only administrators can create a system-wide alert");
|
||||||
|
}
|
||||||
|
systemWideAlertDAO.delete(context, systemWideAlert);
|
||||||
|
log.info(LogHelper.getHeader(context, "system_wide_alert_create",
|
||||||
|
"System Wide Alert with ID " + systemWideAlert.getID() + " has been deleted"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(final Context context, final SystemWideAlert systemWideAlert)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
if (!authorizeService.isAdmin(context)) {
|
||||||
|
throw new AuthorizeException(
|
||||||
|
"Only administrators can create a system-wide alert");
|
||||||
|
}
|
||||||
|
systemWideAlertDAO.save(context, systemWideAlert);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canNonAdminUserLogin(Context context) throws SQLException {
|
||||||
|
List<SystemWideAlert> active = findAllActive(context, 1, 0);
|
||||||
|
if (active == null || active.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return active.get(0).getAllowSessions() == AllowSessionsEnum.ALLOW_ALL_SESSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUserMaintainSession(Context context, EPerson ePerson) throws SQLException {
|
||||||
|
if (authorizeService.isAdmin(context, ePerson)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
List<SystemWideAlert> active = findAllActive(context, 1, 0);
|
||||||
|
if (active == null || active.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return active.get(0).getAllowSessions() != AllowSessionsEnum.ALLOW_ADMIN_SESSIONS_ONLY;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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.alerts.dao;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.alerts.SystemWideAlert;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.core.GenericDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the Data Access Object for the {@link SystemWideAlert} object
|
||||||
|
*/
|
||||||
|
public interface SystemWideAlertDAO extends GenericDAO<SystemWideAlert> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all SystemWideAlert objects in the database
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param limit The limit for the amount of SystemWideAlerts returned
|
||||||
|
* @param offset The offset for the Processes to be returned
|
||||||
|
* @return The list of all SystemWideAlert objects in the Database
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
List<SystemWideAlert> findAll(Context context, int limit, int offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all active SystemWideAlert objects in the database
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param limit The limit for the amount of SystemWideAlerts returned
|
||||||
|
* @param offset The offset for the Processes to be returned
|
||||||
|
* @return The list of all SystemWideAlert objects in the Database
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
List<SystemWideAlert> findAllActive(Context context, int limit, int offset) throws SQLException;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* 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.alerts.dao.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import org.dspace.alerts.SystemWideAlert;
|
||||||
|
import org.dspace.alerts.SystemWideAlert_;
|
||||||
|
import org.dspace.alerts.dao.SystemWideAlertDAO;
|
||||||
|
import org.dspace.core.AbstractHibernateDAO;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation class for the {@link SystemWideAlertDAO}
|
||||||
|
*/
|
||||||
|
public class SystemWideAlertDAOImpl extends AbstractHibernateDAO<SystemWideAlert> implements SystemWideAlertDAO {
|
||||||
|
|
||||||
|
public List<SystemWideAlert> findAll(final Context context, final int limit, final int offset) throws SQLException {
|
||||||
|
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||||
|
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, SystemWideAlert.class);
|
||||||
|
Root<SystemWideAlert> alertRoot = criteriaQuery.from(SystemWideAlert.class);
|
||||||
|
criteriaQuery.select(alertRoot);
|
||||||
|
|
||||||
|
return list(context, criteriaQuery, false, SystemWideAlert.class, limit, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SystemWideAlert> findAllActive(final Context context, final int limit, final int offset)
|
||||||
|
throws SQLException {
|
||||||
|
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||||
|
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, SystemWideAlert.class);
|
||||||
|
Root<SystemWideAlert> alertRoot = criteriaQuery.from(SystemWideAlert.class);
|
||||||
|
criteriaQuery.select(alertRoot);
|
||||||
|
criteriaQuery.where(criteriaBuilder.equal(alertRoot.get(SystemWideAlert_.active), true));
|
||||||
|
|
||||||
|
return list(context, criteriaQuery, false, SystemWideAlert.class, limit, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* 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.alerts.service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.alerts.AllowSessionsEnum;
|
||||||
|
import org.dspace.alerts.SystemWideAlert;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for the SystemWideAlertService with methods regarding the SystemWideAlert workload
|
||||||
|
*/
|
||||||
|
public interface SystemWideAlertService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will create a SystemWideAlert object in the database
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param message The message of the system-wide alert
|
||||||
|
* @param allowSessionsType Which sessions need to be allowed for the system-wide alert
|
||||||
|
* @param countdownTo The date to which to count down to when the system-wide alert is active
|
||||||
|
* @param active Whether the system-wide alert os active
|
||||||
|
* @return The created SystemWideAlert object
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
SystemWideAlert create(Context context, String message, AllowSessionsEnum allowSessionsType,
|
||||||
|
Date countdownTo, boolean active
|
||||||
|
) throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will retrieve a SystemWideAlert object from the Database with the given ID
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param alertId The alert id on which we'll search for in the database
|
||||||
|
* @return The system-wide alert that holds the given alert id
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
SystemWideAlert find(Context context, int alertId) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all SystemWideAlert objects in the database
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @return The list of all SystemWideAlert objects in the Database
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
List<SystemWideAlert> findAll(Context context) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all SystemWideAlert objects in the database
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param limit The limit for the amount of system-wide alerts returned
|
||||||
|
* @param offset The offset for the system-wide alerts to be returned
|
||||||
|
* @return The list of all SystemWideAlert objects in the Database
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
List<SystemWideAlert> findAll(Context context, int limit, int offset) throws SQLException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all active SystemWideAlert objects in the database
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @return The list of all active SystemWideAlert objects in the database
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
List<SystemWideAlert> findAllActive(Context context, int limit, int offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will delete the given SystemWideAlert object from the database
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param systemWideAlert The SystemWideAlert object to be deleted
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
void delete(Context context, SystemWideAlert systemWideAlert)
|
||||||
|
throws SQLException, IOException, AuthorizeException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be used to update the given SystemWideAlert object in the database
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @param systemWideAlert The SystemWideAlert object to be updated
|
||||||
|
* @throws SQLException If something goes wrong
|
||||||
|
*/
|
||||||
|
void update(Context context, SystemWideAlert systemWideAlert) throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies if the user connected to the current context can retain its session
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @return if the user connected to the current context can retain its session
|
||||||
|
*/
|
||||||
|
boolean canUserMaintainSession(Context context, EPerson ePerson) throws SQLException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies if a non admin user can log in
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace context
|
||||||
|
* @return if a non admin user can log in
|
||||||
|
*/
|
||||||
|
boolean canNonAdminUserLogin(Context context) throws SQLException;
|
||||||
|
}
|
@@ -736,7 +736,7 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl<Collection> i
|
|||||||
collection.getID(), collection.getHandle(), getIdentifiers(context, collection)));
|
collection.getID(), collection.getHandle(), getIdentifiers(context, collection)));
|
||||||
|
|
||||||
// remove subscriptions - hmm, should this be in Subscription.java?
|
// remove subscriptions - hmm, should this be in Subscription.java?
|
||||||
subscribeService.deleteByCollection(context, collection);
|
subscribeService.deleteByDspaceObject(context, collection);
|
||||||
|
|
||||||
// Remove Template Item
|
// Remove Template Item
|
||||||
removeTemplateItem(context, collection);
|
removeTemplateItem(context, collection);
|
||||||
|
@@ -36,6 +36,7 @@ import org.dspace.core.I18nUtil;
|
|||||||
import org.dspace.core.LogHelper;
|
import org.dspace.core.LogHelper;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.eperson.service.GroupService;
|
import org.dspace.eperson.service.GroupService;
|
||||||
|
import org.dspace.eperson.service.SubscribeService;
|
||||||
import org.dspace.event.Event;
|
import org.dspace.event.Event;
|
||||||
import org.dspace.identifier.IdentifierException;
|
import org.dspace.identifier.IdentifierException;
|
||||||
import org.dspace.identifier.service.IdentifierService;
|
import org.dspace.identifier.service.IdentifierService;
|
||||||
@@ -73,7 +74,8 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl<Community> imp
|
|||||||
protected SiteService siteService;
|
protected SiteService siteService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected IdentifierService identifierService;
|
protected IdentifierService identifierService;
|
||||||
|
@Autowired(required = true)
|
||||||
|
protected SubscribeService subscribeService;
|
||||||
protected CommunityServiceImpl() {
|
protected CommunityServiceImpl() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -217,12 +219,12 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl<Community> imp
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bitstream setLogo(Context context, Community community, InputStream is)
|
public Bitstream setLogo(Context context, Community community, InputStream is)
|
||||||
throws AuthorizeException, IOException, SQLException {
|
throws AuthorizeException, IOException, SQLException {
|
||||||
// Check authorisation
|
// Check authorisation
|
||||||
// authorized to remove the logo when DELETE rights
|
// authorized to remove the logo when DELETE rights
|
||||||
// authorized when canEdit
|
// authorized when canEdit
|
||||||
if (!((is == null) && authorizeService.authorizeActionBoolean(
|
if (!((is == null) && authorizeService.authorizeActionBoolean(
|
||||||
context, community, Constants.DELETE))) {
|
context, community, Constants.DELETE))) {
|
||||||
canEdit(context, community);
|
canEdit(context, community);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +244,7 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl<Community> imp
|
|||||||
// now create policy for logo bitstream
|
// now create policy for logo bitstream
|
||||||
// to match our READ policy
|
// to match our READ policy
|
||||||
List<ResourcePolicy> policies = authorizeService
|
List<ResourcePolicy> policies = authorizeService
|
||||||
.getPoliciesActionFilter(context, community, Constants.READ);
|
.getPoliciesActionFilter(context, community, Constants.READ);
|
||||||
authorizeService.addPolicies(context, policies, newLogo);
|
authorizeService.addPolicies(context, policies, newLogo);
|
||||||
|
|
||||||
log.info(LogHelper.getHeader(context, "set_logo",
|
log.info(LogHelper.getHeader(context, "set_logo",
|
||||||
@@ -549,6 +551,8 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl<Community> imp
|
|||||||
context.addEvent(new Event(Event.DELETE, Constants.COMMUNITY, community.getID(), community.getHandle(),
|
context.addEvent(new Event(Event.DELETE, Constants.COMMUNITY, community.getID(), community.getHandle(),
|
||||||
getIdentifiers(context, community)));
|
getIdentifiers(context, community)));
|
||||||
|
|
||||||
|
subscribeService.deleteByDspaceObject(context, community);
|
||||||
|
|
||||||
// Remove collections
|
// Remove collections
|
||||||
Iterator<Collection> collections = community.getCollections().iterator();
|
Iterator<Collection> collections = community.getCollections().iterator();
|
||||||
|
|
||||||
|
@@ -10,9 +10,14 @@ package org.dspace.content;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.logic.Filter;
|
||||||
|
import org.dspace.content.logic.FilterUtils;
|
||||||
import org.dspace.content.service.CollectionService;
|
import org.dspace.content.service.CollectionService;
|
||||||
import org.dspace.content.service.InstallItemService;
|
import org.dspace.content.service.InstallItemService;
|
||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
@@ -20,6 +25,7 @@ import org.dspace.core.Constants;
|
|||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.embargo.service.EmbargoService;
|
import org.dspace.embargo.service.EmbargoService;
|
||||||
import org.dspace.event.Event;
|
import org.dspace.event.Event;
|
||||||
|
import org.dspace.identifier.Identifier;
|
||||||
import org.dspace.identifier.IdentifierException;
|
import org.dspace.identifier.IdentifierException;
|
||||||
import org.dspace.identifier.service.IdentifierService;
|
import org.dspace.identifier.service.IdentifierService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -42,9 +48,11 @@ public class InstallItemServiceImpl implements InstallItemService {
|
|||||||
protected IdentifierService identifierService;
|
protected IdentifierService identifierService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected ItemService itemService;
|
protected ItemService itemService;
|
||||||
|
@Autowired(required = false)
|
||||||
|
|
||||||
|
Logger log = LogManager.getLogger(InstallItemServiceImpl.class);
|
||||||
|
|
||||||
protected InstallItemServiceImpl() {
|
protected InstallItemServiceImpl() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -59,10 +67,14 @@ public class InstallItemServiceImpl implements InstallItemService {
|
|||||||
AuthorizeException {
|
AuthorizeException {
|
||||||
Item item = is.getItem();
|
Item item = is.getItem();
|
||||||
Collection collection = is.getCollection();
|
Collection collection = is.getCollection();
|
||||||
|
// Get map of filters to use for identifier types.
|
||||||
|
Map<Class<? extends Identifier>, Filter> filters = FilterUtils.getIdentifierFilters(false);
|
||||||
try {
|
try {
|
||||||
if (suppliedHandle == null) {
|
if (suppliedHandle == null) {
|
||||||
identifierService.register(c, item);
|
// Register with the filters we've set up
|
||||||
|
identifierService.register(c, item, filters);
|
||||||
} else {
|
} else {
|
||||||
|
// This will register the handle but a pending DOI won't be compatible and so won't be registered
|
||||||
identifierService.register(c, item, suppliedHandle);
|
identifierService.register(c, item, suppliedHandle);
|
||||||
}
|
}
|
||||||
} catch (IdentifierException e) {
|
} catch (IdentifierException e) {
|
||||||
|
@@ -61,6 +61,7 @@ import org.dspace.discovery.indexobject.IndexableItem;
|
|||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.eperson.service.GroupService;
|
import org.dspace.eperson.service.GroupService;
|
||||||
|
import org.dspace.eperson.service.SubscribeService;
|
||||||
import org.dspace.event.Event;
|
import org.dspace.event.Event;
|
||||||
import org.dspace.harvest.HarvestedItem;
|
import org.dspace.harvest.HarvestedItem;
|
||||||
import org.dspace.harvest.service.HarvestedItemService;
|
import org.dspace.harvest.service.HarvestedItemService;
|
||||||
@@ -163,6 +164,9 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
|||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
private RequestItemService requestItemService;
|
private RequestItemService requestItemService;
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
protected SubscribeService subscribeService;
|
||||||
|
|
||||||
protected ItemServiceImpl() {
|
protected ItemServiceImpl() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@@ -769,7 +773,8 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
|||||||
|
|
||||||
log.info(LogHelper.getHeader(context, "delete_item", "item_id="
|
log.info(LogHelper.getHeader(context, "delete_item", "item_id="
|
||||||
+ item.getID()));
|
+ item.getID()));
|
||||||
|
//remove subscription related with it
|
||||||
|
subscribeService.deleteByDspaceObject(context, item);
|
||||||
// Remove relationships
|
// Remove relationships
|
||||||
for (Relationship relationship : relationshipService.findByItem(context, item, -1, -1, false, false)) {
|
for (Relationship relationship : relationshipService.findByItem(context, item, -1, -1, false, false)) {
|
||||||
relationshipService.forceDelete(context, relationship, false, false);
|
relationshipService.forceDelete(context, relationship, false, false);
|
||||||
|
@@ -24,6 +24,8 @@ import org.dspace.authorize.AuthorizeException;
|
|||||||
import org.dspace.authorize.ResourcePolicy;
|
import org.dspace.authorize.ResourcePolicy;
|
||||||
import org.dspace.authorize.service.AuthorizeService;
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
import org.dspace.content.dao.WorkspaceItemDAO;
|
import org.dspace.content.dao.WorkspaceItemDAO;
|
||||||
|
import org.dspace.content.logic.Filter;
|
||||||
|
import org.dspace.content.logic.FilterUtils;
|
||||||
import org.dspace.content.service.CollectionService;
|
import org.dspace.content.service.CollectionService;
|
||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
import org.dspace.content.service.WorkspaceItemService;
|
import org.dspace.content.service.WorkspaceItemService;
|
||||||
@@ -32,6 +34,13 @@ import org.dspace.core.Context;
|
|||||||
import org.dspace.core.LogHelper;
|
import org.dspace.core.LogHelper;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.event.Event;
|
import org.dspace.event.Event;
|
||||||
|
import org.dspace.identifier.DOI;
|
||||||
|
import org.dspace.identifier.DOIIdentifierProvider;
|
||||||
|
import org.dspace.identifier.Identifier;
|
||||||
|
import org.dspace.identifier.IdentifierException;
|
||||||
|
import org.dspace.identifier.factory.IdentifierServiceFactory;
|
||||||
|
import org.dspace.identifier.service.DOIService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
import org.dspace.workflow.WorkflowItem;
|
import org.dspace.workflow.WorkflowItem;
|
||||||
import org.dspace.workflow.WorkflowService;
|
import org.dspace.workflow.WorkflowService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -58,6 +67,8 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
|
|||||||
protected ItemService itemService;
|
protected ItemService itemService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected WorkflowService workflowService;
|
protected WorkflowService workflowService;
|
||||||
|
@Autowired(required = true)
|
||||||
|
protected DOIService doiService;
|
||||||
|
|
||||||
|
|
||||||
protected WorkspaceItemServiceImpl() {
|
protected WorkspaceItemServiceImpl() {
|
||||||
@@ -160,6 +171,26 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
itemService.update(context, item);
|
itemService.update(context, item);
|
||||||
|
|
||||||
|
// If configured, register identifiers (eg handle, DOI) now. This is typically used with the Show Identifiers
|
||||||
|
// submission step which previews minted handles and DOIs during the submission process. Default: false
|
||||||
|
if (DSpaceServicesFactory.getInstance().getConfigurationService()
|
||||||
|
.getBooleanProperty("identifiers.submission.register", false)) {
|
||||||
|
try {
|
||||||
|
// Get map of filters to use for identifier types, while the item is in progress
|
||||||
|
Map<Class<? extends Identifier>, Filter> filters = FilterUtils.getIdentifierFilters(true);
|
||||||
|
IdentifierServiceFactory.getInstance().getIdentifierService().register(context, item, filters);
|
||||||
|
// Look for a DOI and move it to PENDING
|
||||||
|
DOI doi = doiService.findDOIByDSpaceObject(context, item);
|
||||||
|
if (doi != null) {
|
||||||
|
doi.setStatus(DOIIdentifierProvider.PENDING);
|
||||||
|
doiService.update(context, doi);
|
||||||
|
}
|
||||||
|
} catch (IdentifierException e) {
|
||||||
|
log.error("Could not register identifier(s) for item {}: {}", item.getID(), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
workspaceItem.setItem(item);
|
workspaceItem.setItem(item);
|
||||||
|
|
||||||
log.info(LogHelper.getHeader(context, "create_workspace_item",
|
log.info(LogHelper.getHeader(context, "create_workspace_item",
|
||||||
|
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* 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.crosswalk;
|
||||||
|
|
||||||
|
import static org.dspace.content.Item.ANY;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.handle.factory.HandleServiceFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a String to be sent as email body for subscriptions
|
||||||
|
*
|
||||||
|
* @author Alba Aliu
|
||||||
|
*/
|
||||||
|
public class SubscriptionDsoMetadataForEmailCompose implements StreamDisseminationCrosswalk {
|
||||||
|
|
||||||
|
private List<String> metadata = new ArrayList<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ItemService itemService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canDisseminate(Context context, DSpaceObject dso) {
|
||||||
|
return Objects.nonNull(dso) && dso.getType() == Constants.ITEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disseminate(Context context, DSpaceObject dso, OutputStream out) throws SQLException {
|
||||||
|
if (dso.getType() == Constants.ITEM) {
|
||||||
|
Item item = (Item) dso;
|
||||||
|
PrintStream printStream = new PrintStream(out);
|
||||||
|
for (String actualMetadata : metadata) {
|
||||||
|
String[] splitted = actualMetadata.split("\\.");
|
||||||
|
String qualifier = null;
|
||||||
|
if (splitted.length == 1) {
|
||||||
|
qualifier = splitted[2];
|
||||||
|
}
|
||||||
|
var metadataValue = itemService.getMetadataFirstValue(item, splitted[0], splitted[1], qualifier, ANY);
|
||||||
|
printStream.print(metadataValue + " ");
|
||||||
|
}
|
||||||
|
String itemURL = HandleServiceFactory.getInstance()
|
||||||
|
.getHandleService()
|
||||||
|
.resolveToURL(context, item.getHandle());
|
||||||
|
printStream.print(itemURL);
|
||||||
|
printStream.print("\n");
|
||||||
|
printStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMIMEType() {
|
||||||
|
return "text/plain";
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadata(List<String> metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -33,6 +33,7 @@ import org.dspace.content.service.RelationshipTypeService;
|
|||||||
import org.dspace.content.service.SiteService;
|
import org.dspace.content.service.SiteService;
|
||||||
import org.dspace.content.service.SupervisedItemService;
|
import org.dspace.content.service.SupervisedItemService;
|
||||||
import org.dspace.content.service.WorkspaceItemService;
|
import org.dspace.content.service.WorkspaceItemService;
|
||||||
|
import org.dspace.eperson.service.SubscribeService;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
import org.dspace.workflow.factory.WorkflowServiceFactory;
|
import org.dspace.workflow.factory.WorkflowServiceFactory;
|
||||||
|
|
||||||
@@ -75,6 +76,8 @@ public abstract class ContentServiceFactory {
|
|||||||
|
|
||||||
public abstract SiteService getSiteService();
|
public abstract SiteService getSiteService();
|
||||||
|
|
||||||
|
public abstract SubscribeService getSubscribeService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the implementation of the RelationshipTypeService interface
|
* Return the implementation of the RelationshipTypeService interface
|
||||||
*
|
*
|
||||||
@@ -114,11 +117,7 @@ public abstract class ContentServiceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T extends DSpaceObject> DSpaceObjectService<T> getDSpaceObjectService(T dso) {
|
public <T extends DSpaceObject> DSpaceObjectService<T> getDSpaceObjectService(T dso) {
|
||||||
// No need to worry when supressing, as long as our "getDSpaceObjectManager" method is properly implemented
|
return getDSpaceObjectService(dso.getType());
|
||||||
// no casting issues should occur
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
DSpaceObjectService<T> manager = getDSpaceObjectService(dso.getType());
|
|
||||||
return manager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@@ -30,6 +30,7 @@ import org.dspace.content.service.RelationshipTypeService;
|
|||||||
import org.dspace.content.service.SiteService;
|
import org.dspace.content.service.SiteService;
|
||||||
import org.dspace.content.service.SupervisedItemService;
|
import org.dspace.content.service.SupervisedItemService;
|
||||||
import org.dspace.content.service.WorkspaceItemService;
|
import org.dspace.content.service.WorkspaceItemService;
|
||||||
|
import org.dspace.eperson.service.SubscribeService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +72,8 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory {
|
|||||||
private SupervisedItemService supervisedItemService;
|
private SupervisedItemService supervisedItemService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
private SiteService siteService;
|
private SiteService siteService;
|
||||||
|
@Autowired(required = true)
|
||||||
|
private SubscribeService subscribeService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
private RelationshipService relationshipService;
|
private RelationshipService relationshipService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
@@ -158,6 +160,11 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory {
|
|||||||
return siteService;
|
return siteService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubscribeService getSubscribeService() {
|
||||||
|
return subscribeService ;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RelationshipTypeService getRelationshipTypeService() {
|
public RelationshipTypeService getRelationshipTypeService() {
|
||||||
return relationshipTypeService;
|
return relationshipTypeService;
|
||||||
|
@@ -18,10 +18,10 @@ import org.dspace.core.Context;
|
|||||||
* statement as a property (unlike an operator) and takes no parameters (unlike a condition)
|
* statement as a property (unlike an operator) and takes no parameters (unlike a condition)
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class DefaultFilter implements Filter {
|
public class DefaultFilter implements Filter {
|
||||||
private LogicalStatement statement;
|
private LogicalStatement statement;
|
||||||
|
private String name;
|
||||||
private final static Logger log = LogManager.getLogger();
|
private final static Logger log = LogManager.getLogger();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,4 +44,15 @@ public class DefaultFilter implements Filter {
|
|||||||
public boolean getResult(Context context, Item item) throws LogicalStatementException {
|
public boolean getResult(Context context, Item item) throws LogicalStatementException {
|
||||||
return this.statement.getResult(context, item);
|
return this.statement.getResult(context, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBeanName(String name) {
|
||||||
|
log.debug("Initialize bean " + name);
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ package org.dspace.content.logic;
|
|||||||
|
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.beans.factory.BeanNameAware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface for Filter currently doesn't add anything to LogicalStatement but inherits from it
|
* The interface for Filter currently doesn't add anything to LogicalStatement but inherits from it
|
||||||
@@ -22,7 +23,7 @@ import org.dspace.core.Context;
|
|||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @see org.dspace.content.logic.DefaultFilter
|
* @see org.dspace.content.logic.DefaultFilter
|
||||||
*/
|
*/
|
||||||
public interface Filter extends LogicalStatement {
|
public interface Filter extends LogicalStatement, BeanNameAware {
|
||||||
/**
|
/**
|
||||||
* Get the result of logical evaluation for an item
|
* Get the result of logical evaluation for an item
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
@@ -32,4 +33,11 @@ public interface Filter extends LogicalStatement {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
boolean getResult(Context context, Item item) throws LogicalStatementException;
|
boolean getResult(Context context, Item item) throws LogicalStatementException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of a filter. This can be used by filters which make use of BeanNameAware
|
||||||
|
* to return the bean name.
|
||||||
|
* @return the id/name of this spring bean
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* 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.logic;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.dspace.identifier.DOI;
|
||||||
|
import org.dspace.identifier.Handle;
|
||||||
|
import org.dspace.identifier.Identifier;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General utility methods for logical item filtering
|
||||||
|
*
|
||||||
|
* @author Kim Shepherd
|
||||||
|
*/
|
||||||
|
public class FilterUtils {
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
ConfigurationService configurationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a Filter by configuration property name
|
||||||
|
* For example, if a module has implemented "my-feature.filter" configuration property
|
||||||
|
* this method will return a filter with the ID specified by the configuration property
|
||||||
|
* @param property DSpace configuration property name (Apache Commons config)
|
||||||
|
* @return Filter object, with a bean ID configured for this property key, or null
|
||||||
|
*/
|
||||||
|
public static Filter getFilterFromConfiguration(String property) {
|
||||||
|
String filterName = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty(property);
|
||||||
|
if (filterName != null) {
|
||||||
|
return DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(filterName, Filter.class);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a Filter by configuration property name
|
||||||
|
* For example, if a module has implemented "my-feature.filter" configuration property
|
||||||
|
* this method will return a filter with the ID specified by the configuration property
|
||||||
|
* @param property DSpace configuration property name (Apache Commons config)
|
||||||
|
* @return Filter object, with a bean ID configured for this property key, or default filter
|
||||||
|
*/
|
||||||
|
public static Filter getFilterFromConfiguration(String property, Filter defaultFilter) {
|
||||||
|
Filter filter = getFilterFromConfiguration(property);
|
||||||
|
if (filter != null) {
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
return defaultFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a map of identifier types and filters to use when creating workspace or archived items
|
||||||
|
* This is used by services installing new archived or workspace items to filter by identifier type
|
||||||
|
* as some filters should apply to DOI creation but not Handle creation, and so on.
|
||||||
|
* The in progress or archived status will be used to load the appropriate filter from configuration
|
||||||
|
* <p>
|
||||||
|
* @param inProgress
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Map<Class<? extends Identifier>, Filter> getIdentifierFilters(boolean inProgress) {
|
||||||
|
String configurationSuffix = "install";
|
||||||
|
if (inProgress) {
|
||||||
|
configurationSuffix = "workspace";
|
||||||
|
}
|
||||||
|
Map<Class<? extends Identifier>, Filter> filters = new HashMap<>();
|
||||||
|
// Put DOI 'can we create DOI on install / workspace?' filter
|
||||||
|
Filter filter = FilterUtils.getFilterFromConfiguration("identifiers.submission.filter." + configurationSuffix);
|
||||||
|
// A null filter should be handled safely by the identifier provier (default, or "always true")
|
||||||
|
filters.put(DOI.class, filter);
|
||||||
|
// This won't have an affect until handle providers implement filtering, but is an example of
|
||||||
|
// how the filters can be used for other types
|
||||||
|
filters.put(Handle.class, DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
|
||||||
|
"always_true_filter", TrueFilter.class));
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
}
|
@@ -17,7 +17,6 @@ import org.dspace.core.Context;
|
|||||||
* used as sub-statements in other Filters and Operators.
|
* used as sub-statements in other Filters and Operators.
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public interface LogicalStatement {
|
public interface LogicalStatement {
|
||||||
/**
|
/**
|
||||||
|
@@ -12,7 +12,6 @@ package org.dspace.content.logic;
|
|||||||
* defined as spring beans.
|
* defined as spring beans.
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class LogicalStatementException extends RuntimeException {
|
public class LogicalStatementException extends RuntimeException {
|
||||||
|
|
||||||
|
@@ -33,7 +33,6 @@ import org.dspace.services.factory.DSpaceServicesFactory;
|
|||||||
* A command-line runner used for testing a logical filter against an item, or all items
|
* A command-line runner used for testing a logical filter against an item, or all items
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class TestLogicRunner {
|
public class TestLogicRunner {
|
||||||
|
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.logic;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extremely simple filter that always returns true!
|
||||||
|
* Useful to pass to methods that expect a filter, in order to effectively say "all items".
|
||||||
|
* This could be configured in Spring XML but it is more stable and reliable to have it hard-coded here
|
||||||
|
* so that any broken configuration doesn't silently break parts of DSpace that expect it to work.
|
||||||
|
*
|
||||||
|
* @author Kim Shepherd
|
||||||
|
*/
|
||||||
|
public class TrueFilter implements Filter {
|
||||||
|
private String name;
|
||||||
|
private final static Logger log = LogManager.getLogger();
|
||||||
|
|
||||||
|
public boolean getResult(Context context, Item item) throws LogicalStatementException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBeanName(String name) {
|
||||||
|
log.debug("Initialize bean " + name);
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@@ -23,7 +23,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
* Abstract class for conditions, to implement the basic getter and setter parameters
|
* Abstract class for conditions, to implement the basic getter and setter parameters
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCondition implements Condition {
|
public abstract class AbstractCondition implements Condition {
|
||||||
|
|
||||||
|
@@ -18,7 +18,6 @@ import org.dspace.core.Context;
|
|||||||
* A condition to evaluate an item based on how many bitstreams it has in a particular bundle
|
* A condition to evaluate an item based on how many bitstreams it has in a particular bundle
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class BitstreamCountCondition extends AbstractCondition {
|
public class BitstreamCountCondition extends AbstractCondition {
|
||||||
/**
|
/**
|
||||||
|
@@ -22,7 +22,6 @@ import org.dspace.core.Context;
|
|||||||
* operator is not a condition but also a logical statement.
|
* operator is not a condition but also a logical statement.
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public interface Condition extends LogicalStatement {
|
public interface Condition extends LogicalStatement {
|
||||||
|
|
||||||
|
@@ -23,7 +23,6 @@ import org.dspace.core.Context;
|
|||||||
* if the item belongs to any of them.
|
* if the item belongs to any of them.
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class InCollectionCondition extends AbstractCondition {
|
public class InCollectionCondition extends AbstractCondition {
|
||||||
private static Logger log = LogManager.getLogger(InCollectionCondition.class);
|
private static Logger log = LogManager.getLogger(InCollectionCondition.class);
|
||||||
|
@@ -24,7 +24,6 @@ import org.dspace.core.Context;
|
|||||||
* if the item belongs to any of them.
|
* if the item belongs to any of them.
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class InCommunityCondition extends AbstractCondition {
|
public class InCommunityCondition extends AbstractCondition {
|
||||||
private final static Logger log = LogManager.getLogger();
|
private final static Logger log = LogManager.getLogger();
|
||||||
|
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* 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.logic.condition;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.logic.LogicalStatementException;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A condition that returns true if the item is archived
|
||||||
|
*
|
||||||
|
* @author Kim Shepherd
|
||||||
|
*/
|
||||||
|
public class IsArchivedCondition extends AbstractCondition {
|
||||||
|
private final static Logger log = LogManager.getLogger();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if item is archived
|
||||||
|
* Return false if not
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param item Item to evaluate
|
||||||
|
* @return boolean result of evaluation
|
||||||
|
* @throws LogicalStatementException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean getResult(Context context, Item item) throws LogicalStatementException {
|
||||||
|
log.debug("Result of isArchived is " + item.isArchived());
|
||||||
|
return item.isArchived();
|
||||||
|
}
|
||||||
|
}
|
@@ -17,7 +17,6 @@ import org.dspace.core.Context;
|
|||||||
* A condition that returns true if the item is withdrawn
|
* A condition that returns true if the item is withdrawn
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class IsWithdrawnCondition extends AbstractCondition {
|
public class IsWithdrawnCondition extends AbstractCondition {
|
||||||
private final static Logger log = LogManager.getLogger();
|
private final static Logger log = LogManager.getLogger();
|
||||||
|
@@ -23,7 +23,6 @@ import org.dspace.core.Context;
|
|||||||
* in a given metadata field
|
* in a given metadata field
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class MetadataValueMatchCondition extends AbstractCondition {
|
public class MetadataValueMatchCondition extends AbstractCondition {
|
||||||
|
|
||||||
|
@@ -23,7 +23,6 @@ import org.dspace.core.Context;
|
|||||||
* in a given metadata field
|
* in a given metadata field
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class MetadataValuesMatchCondition extends AbstractCondition {
|
public class MetadataValuesMatchCondition extends AbstractCondition {
|
||||||
|
|
||||||
|
@@ -25,7 +25,6 @@ import org.dspace.core.Context;
|
|||||||
* can perform the action on a given item
|
* can perform the action on a given item
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class ReadableByGroupCondition extends AbstractCondition {
|
public class ReadableByGroupCondition extends AbstractCondition {
|
||||||
private final static Logger log = LogManager.getLogger();
|
private final static Logger log = LogManager.getLogger();
|
||||||
|
@@ -22,7 +22,6 @@ import org.dspace.core.Context;
|
|||||||
* as a logical result
|
* as a logical result
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractOperator implements LogicalStatement {
|
public abstract class AbstractOperator implements LogicalStatement {
|
||||||
|
|
||||||
|
@@ -19,7 +19,6 @@ import org.dspace.core.Context;
|
|||||||
* true if all sub-statements return true
|
* true if all sub-statements return true
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class And extends AbstractOperator {
|
public class And extends AbstractOperator {
|
||||||
|
|
||||||
|
@@ -18,7 +18,6 @@ import org.dspace.core.Context;
|
|||||||
* An operator that implements NAND by negating an AND operation
|
* An operator that implements NAND by negating an AND operation
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class Nand extends AbstractOperator {
|
public class Nand extends AbstractOperator {
|
||||||
|
|
||||||
|
@@ -19,7 +19,6 @@ import org.dspace.core.Context;
|
|||||||
* Not can have one sub-statement only, while and, or, nor, ... can have multiple sub-statements.
|
* Not can have one sub-statement only, while and, or, nor, ... can have multiple sub-statements.
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class Not implements LogicalStatement {
|
public class Not implements LogicalStatement {
|
||||||
|
|
||||||
|
@@ -19,7 +19,6 @@ import org.dspace.core.Context;
|
|||||||
* true if one or more sub-statements return true
|
* true if one or more sub-statements return true
|
||||||
*
|
*
|
||||||
* @author Kim Shepherd
|
* @author Kim Shepherd
|
||||||
* @version $Revision$
|
|
||||||
*/
|
*/
|
||||||
public class Or extends AbstractOperator {
|
public class Or extends AbstractOperator {
|
||||||
|
|
||||||
|
@@ -13,11 +13,15 @@ import java.sql.SQLException;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.logic.Filter;
|
||||||
|
import org.dspace.content.logic.FilterUtils;
|
||||||
|
import org.dspace.content.logic.TrueFilter;
|
||||||
import org.dspace.curate.AbstractCurationTask;
|
import org.dspace.curate.AbstractCurationTask;
|
||||||
import org.dspace.curate.Curator;
|
import org.dspace.curate.Curator;
|
||||||
import org.dspace.identifier.DOIIdentifierProvider;
|
import org.dspace.identifier.DOIIdentifierProvider;
|
||||||
import org.dspace.identifier.IdentifierException;
|
import org.dspace.identifier.IdentifierException;
|
||||||
import org.dspace.identifier.doi.DOIIdentifierNotApplicableException;
|
import org.dspace.identifier.doi.DOIIdentifierNotApplicableException;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
import org.dspace.utils.DSpace;
|
import org.dspace.utils.DSpace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,6 +43,7 @@ public class RegisterDOI extends AbstractCurationTask {
|
|||||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RegisterDOI.class);
|
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RegisterDOI.class);
|
||||||
// DOI provider
|
// DOI provider
|
||||||
private DOIIdentifierProvider provider;
|
private DOIIdentifierProvider provider;
|
||||||
|
private Filter trueFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise the curation task and read configuration, instantiate the DOI provider
|
* Initialise the curation task and read configuration, instantiate the DOI provider
|
||||||
@@ -46,14 +51,14 @@ public class RegisterDOI extends AbstractCurationTask {
|
|||||||
@Override
|
@Override
|
||||||
public void init(Curator curator, String taskId) throws IOException {
|
public void init(Curator curator, String taskId) throws IOException {
|
||||||
super.init(curator, taskId);
|
super.init(curator, taskId);
|
||||||
// Get 'skip filter' behaviour from configuration, with a default value of 'true'
|
|
||||||
skipFilter = configurationService.getBooleanProperty(PLUGIN_PREFIX + ".skip-filter", true);
|
|
||||||
// Get distribution behaviour from configuration, with a default value of 'false'
|
// Get distribution behaviour from configuration, with a default value of 'false'
|
||||||
distributed = configurationService.getBooleanProperty(PLUGIN_PREFIX + ".distributed", false);
|
distributed = configurationService.getBooleanProperty(PLUGIN_PREFIX + ".distributed", false);
|
||||||
log.debug("PLUGIN_PREFIX = " + PLUGIN_PREFIX + ", skipFilter = " + skipFilter +
|
log.debug("PLUGIN_PREFIX = " + PLUGIN_PREFIX + ", skipFilter = " + skipFilter +
|
||||||
", distributed = " + distributed);
|
", distributed = " + distributed);
|
||||||
// Instantiate DOI provider singleton
|
// Instantiate DOI provider singleton
|
||||||
provider = new DSpace().getSingletonService(DOIIdentifierProvider.class);
|
provider = new DSpace().getSingletonService(DOIIdentifierProvider.class);
|
||||||
|
trueFilter = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
|
||||||
|
"always_true_filter", TrueFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,8 +123,9 @@ public class RegisterDOI extends AbstractCurationTask {
|
|||||||
String doi = null;
|
String doi = null;
|
||||||
// Attempt DOI registration and report successes and failures
|
// Attempt DOI registration and report successes and failures
|
||||||
try {
|
try {
|
||||||
log.debug("Registering DOI with skipFilter = " + skipFilter);
|
Filter filter = FilterUtils.getFilterFromConfiguration("identifiers.submission.filter.curation",
|
||||||
doi = provider.register(Curator.curationContext(), item, skipFilter);
|
trueFilter);
|
||||||
|
doi = provider.register(Curator.curationContext(), item, filter);
|
||||||
if (doi != null) {
|
if (doi != null) {
|
||||||
String message = "New DOI minted in database for item " + item.getHandle() + ": " + doi
|
String message = "New DOI minted in database for item " + item.getHandle() + ": " + doi
|
||||||
+ ". This DOI will be registered online with the DOI provider when the queue is next run";
|
+ ". This DOI will be registered online with the DOI provider when the queue is next run";
|
||||||
|
@@ -139,4 +139,23 @@ public class DiscoveryConfigurationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of all DiscoveryConfiguration objects where key starts with prefixConfigurationName
|
||||||
|
*
|
||||||
|
* @param prefixConfigurationName string as prefix key
|
||||||
|
*/
|
||||||
|
public List<DiscoveryConfiguration> getDiscoveryConfigurationWithPrefixName(final String prefixConfigurationName) {
|
||||||
|
List<DiscoveryConfiguration> discoveryConfigurationList = new ArrayList<>();
|
||||||
|
if (StringUtils.isNotBlank(prefixConfigurationName)) {
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
if (key.equals(prefixConfigurationName) || key.startsWith(prefixConfigurationName)) {
|
||||||
|
DiscoveryConfiguration config = map.get(key);
|
||||||
|
discoveryConfigurationList.add(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return discoveryConfigurationList;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* 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.discovery.configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class extends {@link DiscoveryConfiguration} and add method for set parameters
|
||||||
|
* to filter query list
|
||||||
|
*
|
||||||
|
* @author Danilo Di Nuzzo (danilo.dinuzzo at 4science.it)
|
||||||
|
*/
|
||||||
|
public class DiscoveryRelatedItemConfiguration extends DiscoveryConfiguration {}
|
@@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* 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.discovery.configuration;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Extension of {@link DiscoverySortFieldConfiguration} used to configure sorting
|
||||||
|
* taking advantage of solr function feature.
|
||||||
|
*
|
||||||
|
* Order is evaluated by mean of function parameter value and passed in arguments as input.
|
||||||
|
*
|
||||||
|
* @author Corrado Lombardi (corrado.lombardi at 4science.it)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DiscoverySortFunctionConfiguration extends DiscoverySortFieldConfiguration {
|
||||||
|
|
||||||
|
public static final String SORT_FUNCTION = "sort_function";
|
||||||
|
private String function;
|
||||||
|
private List<String> arguments;
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
public void setFunction(final String function) {
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArguments(final List<String> arguments) {
|
||||||
|
this.arguments = arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return SORT_FUNCTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMetadataField() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the function to be used by solr to sort result
|
||||||
|
* @param functionArgs variable arguments to be inserted in function
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getFunction(final Serializable... functionArgs) {
|
||||||
|
final String args = String.join(",", Optional.ofNullable(arguments).orElse(Collections.emptyList()));
|
||||||
|
final String result = function + "(" + args + ")";
|
||||||
|
return MessageFormat.format(result, functionArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* 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.eperson;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This enum holds all the possible frequency types
|
||||||
|
* that can be used in "subscription-send" script
|
||||||
|
*
|
||||||
|
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||||
|
*/
|
||||||
|
public enum FrequencyType {
|
||||||
|
DAY("D"),
|
||||||
|
WEEK("W"),
|
||||||
|
MONTH("M");
|
||||||
|
|
||||||
|
private String shortName;
|
||||||
|
|
||||||
|
private FrequencyType(String shortName) {
|
||||||
|
this.shortName = shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String findLastFrequency(String frequency) {
|
||||||
|
String startDate = "";
|
||||||
|
String endDate = "";
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
// Full ISO 8601 is e.g.
|
||||||
|
SimpleDateFormat fullIsoStart = new SimpleDateFormat("yyyy-MM-dd'T'00:00:00'Z'");
|
||||||
|
SimpleDateFormat fullIsoEnd = new SimpleDateFormat("yyyy-MM-dd'T'23:59:59'Z'");
|
||||||
|
switch (frequency) {
|
||||||
|
case "D":
|
||||||
|
cal.add(Calendar.DAY_OF_MONTH, -1);
|
||||||
|
endDate = fullIsoEnd.format(cal.getTime());
|
||||||
|
startDate = fullIsoStart.format(cal.getTime());
|
||||||
|
break;
|
||||||
|
case "M":
|
||||||
|
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
|
||||||
|
cal.add(Calendar.DAY_OF_MONTH, -dayOfMonth);
|
||||||
|
endDate = fullIsoEnd.format(cal.getTime());
|
||||||
|
cal.add(Calendar.MONTH, -1);
|
||||||
|
cal.add(Calendar.DAY_OF_MONTH, 1);
|
||||||
|
startDate = fullIsoStart.format(cal.getTime());
|
||||||
|
break;
|
||||||
|
case "W":
|
||||||
|
cal.add(Calendar.DAY_OF_WEEK, -1);
|
||||||
|
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;
|
||||||
|
cal.add(Calendar.DAY_OF_WEEK, -dayOfWeek);
|
||||||
|
endDate = fullIsoEnd.format(cal.getTime());
|
||||||
|
cal.add(Calendar.DAY_OF_WEEK, -6);
|
||||||
|
startDate = fullIsoStart.format(cal.getTime());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return "[" + startDate + " TO " + endDate + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSupportedFrequencyType(String value) {
|
||||||
|
for (FrequencyType ft : Arrays.asList(FrequencyType.values())) {
|
||||||
|
if (StringUtils.equals(ft.getShortName(), value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getShortName() {
|
||||||
|
return shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,432 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.eperson;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
import javax.mail.MessagingException;
|
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
|
||||||
import org.apache.commons.cli.DefaultParser;
|
|
||||||
import org.apache.commons.cli.HelpFormatter;
|
|
||||||
import org.apache.commons.cli.Option;
|
|
||||||
import org.apache.commons.cli.Options;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.dspace.content.Collection;
|
|
||||||
import org.dspace.content.DCDate;
|
|
||||||
import org.dspace.content.Item;
|
|
||||||
import org.dspace.content.MetadataSchemaEnum;
|
|
||||||
import org.dspace.content.MetadataValue;
|
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
|
||||||
import org.dspace.content.service.ItemService;
|
|
||||||
import org.dspace.core.Context;
|
|
||||||
import org.dspace.core.Email;
|
|
||||||
import org.dspace.core.I18nUtil;
|
|
||||||
import org.dspace.core.LogHelper;
|
|
||||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
|
||||||
import org.dspace.eperson.service.SubscribeService;
|
|
||||||
import org.dspace.handle.factory.HandleServiceFactory;
|
|
||||||
import org.dspace.handle.service.HandleService;
|
|
||||||
import org.dspace.search.Harvest;
|
|
||||||
import org.dspace.search.HarvestedItemInfo;
|
|
||||||
import org.dspace.services.ConfigurationService;
|
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CLI tool used for sending new item e-mail alerts to users
|
|
||||||
*
|
|
||||||
* @author Robert Tansley
|
|
||||||
* @version $Revision$
|
|
||||||
*/
|
|
||||||
public class SubscribeCLITool {
|
|
||||||
|
|
||||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SubscribeCLITool.class);
|
|
||||||
|
|
||||||
private static final HandleService handleService
|
|
||||||
= HandleServiceFactory.getInstance().getHandleService();
|
|
||||||
private static final ItemService itemService
|
|
||||||
= ContentServiceFactory.getInstance().getItemService();
|
|
||||||
private static final SubscribeService subscribeService
|
|
||||||
= EPersonServiceFactory.getInstance().getSubscribeService();
|
|
||||||
private static final ConfigurationService configurationService
|
|
||||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor
|
|
||||||
*/
|
|
||||||
private SubscribeCLITool() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process subscriptions. This must be invoked only once a day. Messages are
|
|
||||||
* only sent out when a collection has actually received new items, so that
|
|
||||||
* people's mailboxes are not clogged with many "no new items" mails.
|
|
||||||
* <p>
|
|
||||||
* Yesterday's newly available items are included. If this is run at for
|
|
||||||
* example midday, any items that have been made available during the
|
|
||||||
* current day will not be included, but will be included in the next day's
|
|
||||||
* run.
|
|
||||||
* <p>
|
|
||||||
* For example, if today's date is 2002-10-10 (in UTC) items made available
|
|
||||||
* during 2002-10-09 (UTC) will be included.
|
|
||||||
*
|
|
||||||
* @param context The relevant DSpace Context.
|
|
||||||
* @param test If true, do a "dry run", i.e. don't actually send email, just log the attempt
|
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
|
||||||
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
|
||||||
*/
|
|
||||||
public static void processDaily(Context context, boolean test) throws SQLException,
|
|
||||||
IOException {
|
|
||||||
// Grab the subscriptions
|
|
||||||
|
|
||||||
List<Subscription> subscriptions = subscribeService.findAll(context);
|
|
||||||
|
|
||||||
EPerson currentEPerson = null;
|
|
||||||
List<Collection> collections = null; // List of Collections
|
|
||||||
|
|
||||||
// Go through the list collating subscriptions for each e-person
|
|
||||||
for (Subscription subscription : subscriptions) {
|
|
||||||
// Does this row relate to the same e-person as the last?
|
|
||||||
if ((currentEPerson == null)
|
|
||||||
|| (!subscription.getePerson().getID().equals(currentEPerson
|
|
||||||
.getID()))) {
|
|
||||||
// New e-person. Send mail for previous e-person
|
|
||||||
if (currentEPerson != null) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
sendEmail(context, currentEPerson, collections, test);
|
|
||||||
} catch (MessagingException me) {
|
|
||||||
log.error("Failed to send subscription to eperson_id="
|
|
||||||
+ currentEPerson.getID());
|
|
||||||
log.error(me);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentEPerson = subscription.getePerson();
|
|
||||||
collections = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
collections.add(subscription.getCollection());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the last person
|
|
||||||
if (currentEPerson != null) {
|
|
||||||
try {
|
|
||||||
sendEmail(context, currentEPerson, collections, test);
|
|
||||||
} catch (MessagingException me) {
|
|
||||||
log.error("Failed to send subscription to eperson_id="
|
|
||||||
+ currentEPerson.getID());
|
|
||||||
log.error(me);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends an email to the given e-person with details of new items in the
|
|
||||||
* given collections, items that appeared yesterday. No e-mail is sent if
|
|
||||||
* there aren't any new items in any of the collections.
|
|
||||||
*
|
|
||||||
* @param context DSpace context object
|
|
||||||
* @param eperson eperson to send to
|
|
||||||
* @param collections List of collection IDs (Integers)
|
|
||||||
* @param test If true, do a "dry run", i.e. don't actually send email, just log the attempt
|
|
||||||
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
|
||||||
* @throws MessagingException A general class of exceptions for sending email.
|
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
|
||||||
*/
|
|
||||||
public static void sendEmail(Context context, EPerson eperson,
|
|
||||||
List<Collection> collections, boolean test) throws IOException, MessagingException,
|
|
||||||
SQLException {
|
|
||||||
// Get a resource bundle according to the eperson language preferences
|
|
||||||
Locale supportedLocale = I18nUtil.getEPersonLocale(eperson);
|
|
||||||
ResourceBundle labels = ResourceBundle.getBundle("Messages", supportedLocale);
|
|
||||||
|
|
||||||
// Get the start and end dates for yesterday
|
|
||||||
|
|
||||||
// The date should reflect the timezone as well. Otherwise we stand to lose that information
|
|
||||||
// in truncation and roll to an earlier date than intended.
|
|
||||||
Calendar cal = Calendar.getInstance(TimeZone.getDefault());
|
|
||||||
cal.setTime(new Date());
|
|
||||||
|
|
||||||
// What we actually want to pass to Harvest is "Midnight of yesterday in my current timezone"
|
|
||||||
// Truncation will actually pass in "Midnight of yesterday in UTC", which will be,
|
|
||||||
// at least in CDT, "7pm, the day before yesterday, in my current timezone".
|
|
||||||
cal.add(Calendar.HOUR, -24);
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
||||||
cal.set(Calendar.MINUTE, 0);
|
|
||||||
cal.set(Calendar.SECOND, 0);
|
|
||||||
Date midnightYesterday = cal.getTime();
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: text of email should be more configurable from an
|
|
||||||
// i18n viewpoint
|
|
||||||
StringBuilder emailText = new StringBuilder();
|
|
||||||
boolean isFirst = true;
|
|
||||||
|
|
||||||
for (int i = 0; i < collections.size(); i++) {
|
|
||||||
Collection c = collections.get(i);
|
|
||||||
|
|
||||||
try {
|
|
||||||
boolean includeAll = configurationService
|
|
||||||
.getBooleanProperty("harvest.includerestricted.subscription", true);
|
|
||||||
|
|
||||||
// we harvest all the changed item from yesterday until now
|
|
||||||
List<HarvestedItemInfo> itemInfos = Harvest
|
|
||||||
.harvest(context, c, new DCDate(midnightYesterday).toString(), null, 0, // Limit
|
|
||||||
// and
|
|
||||||
// offset
|
|
||||||
// zero,
|
|
||||||
// get
|
|
||||||
// everything
|
|
||||||
0, true, // Need item objects
|
|
||||||
false, // But not containers
|
|
||||||
false, // Or withdrawals
|
|
||||||
includeAll);
|
|
||||||
|
|
||||||
if (configurationService.getBooleanProperty("eperson.subscription.onlynew", false)) {
|
|
||||||
// get only the items archived yesterday
|
|
||||||
itemInfos = filterOutModified(itemInfos);
|
|
||||||
} else {
|
|
||||||
// strip out the item archived today or
|
|
||||||
// not archived yesterday and modified today
|
|
||||||
itemInfos = filterOutToday(itemInfos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only add to buffer if there are new items
|
|
||||||
if (itemInfos.size() > 0) {
|
|
||||||
if (!isFirst) {
|
|
||||||
emailText
|
|
||||||
.append("\n---------------------------------------\n");
|
|
||||||
} else {
|
|
||||||
isFirst = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
emailText.append(labels.getString("org.dspace.eperson.Subscribe.new-items")).append(" ").append(
|
|
||||||
c.getName()).append(": ").append(
|
|
||||||
itemInfos.size()).append("\n\n");
|
|
||||||
|
|
||||||
for (int j = 0; j < itemInfos.size(); j++) {
|
|
||||||
HarvestedItemInfo hii = (HarvestedItemInfo) itemInfos
|
|
||||||
.get(j);
|
|
||||||
|
|
||||||
String title = hii.item.getName();
|
|
||||||
emailText.append(" ").append(labels.getString("org.dspace.eperson.Subscribe.title"))
|
|
||||||
.append(" ");
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(title)) {
|
|
||||||
emailText.append(title);
|
|
||||||
} else {
|
|
||||||
emailText.append(labels.getString("org.dspace.eperson.Subscribe.untitled"));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MetadataValue> authors = itemService
|
|
||||||
.getMetadata(hii.item, MetadataSchemaEnum.DC.getName(), "contributor", Item.ANY, Item.ANY);
|
|
||||||
|
|
||||||
if (authors.size() > 0) {
|
|
||||||
emailText.append("\n ").append(labels.getString("org.dspace.eperson.Subscribe.authors"))
|
|
||||||
.append(" ").append(
|
|
||||||
authors.get(0).getValue());
|
|
||||||
|
|
||||||
for (int k = 1; k < authors.size(); k++) {
|
|
||||||
emailText.append("\n ").append(
|
|
||||||
authors.get(k).getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emailText.append("\n ").append(labels.getString("org.dspace.eperson.Subscribe.id"))
|
|
||||||
.append(" ").append(
|
|
||||||
handleService.getCanonicalForm(hii.handle)).append(
|
|
||||||
"\n\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ParseException pe) {
|
|
||||||
// This should never get thrown as the Dates are auto-generated
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send an e-mail if there were any new items
|
|
||||||
if (emailText.length() > 0) {
|
|
||||||
|
|
||||||
if (test) {
|
|
||||||
log.info(LogHelper.getHeader(context, "subscription:", "eperson=" + eperson.getEmail()));
|
|
||||||
log.info(LogHelper.getHeader(context, "subscription:", "text=" + emailText.toString()));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "subscription"));
|
|
||||||
email.addRecipient(eperson.getEmail());
|
|
||||||
email.addArgument(emailText.toString());
|
|
||||||
email.send();
|
|
||||||
|
|
||||||
log.info(LogHelper.getHeader(context, "sent_subscription", "eperson_id=" + eperson.getID()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method for invoking subscriptions via the command line
|
|
||||||
*
|
|
||||||
* @param argv the command line arguments given
|
|
||||||
*/
|
|
||||||
public static void main(String[] argv) {
|
|
||||||
String usage = "org.dspace.eperson.Subscribe [-t] or nothing to send out subscriptions.";
|
|
||||||
|
|
||||||
Options options = new Options();
|
|
||||||
HelpFormatter formatter = new HelpFormatter();
|
|
||||||
CommandLine line = null;
|
|
||||||
|
|
||||||
{
|
|
||||||
Option opt = new Option("t", "test", false, "Run test session");
|
|
||||||
opt.setRequired(false);
|
|
||||||
options.addOption(opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Option opt = new Option("h", "help", false, "Print this help message");
|
|
||||||
opt.setRequired(false);
|
|
||||||
options.addOption(opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
line = new DefaultParser().parse(options, argv);
|
|
||||||
} catch (org.apache.commons.cli.ParseException e) {
|
|
||||||
// automatically generate the help statement
|
|
||||||
formatter.printHelp(usage, e.getMessage(), options, "");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.hasOption("h")) {
|
|
||||||
// automatically generate the help statement
|
|
||||||
formatter.printHelp(usage, options);
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean test = line.hasOption("t");
|
|
||||||
|
|
||||||
Context context = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
context = new Context(Context.Mode.READ_ONLY);
|
|
||||||
processDaily(context, test);
|
|
||||||
context.complete();
|
|
||||||
} catch (IOException | SQLException e) {
|
|
||||||
log.fatal(e);
|
|
||||||
} finally {
|
|
||||||
if (context != null && context.isValid()) {
|
|
||||||
// Nothing is actually written
|
|
||||||
context.abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<HarvestedItemInfo> filterOutToday(List<HarvestedItemInfo> completeList) {
|
|
||||||
log.debug("Filtering out all today item to leave new items list size="
|
|
||||||
+ completeList.size());
|
|
||||||
List<HarvestedItemInfo> filteredList = new ArrayList<>();
|
|
||||||
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
|
||||||
String today = sdf.format(new Date());
|
|
||||||
// Get the start and end dates for yesterday
|
|
||||||
Date thisTimeYesterday = new Date(System.currentTimeMillis()
|
|
||||||
- (24 * 60 * 60 * 1000));
|
|
||||||
String yesterday = sdf.format(thisTimeYesterday);
|
|
||||||
|
|
||||||
for (HarvestedItemInfo infoObject : completeList) {
|
|
||||||
Date lastUpdate = infoObject.item.getLastModified();
|
|
||||||
String lastUpdateStr = sdf.format(lastUpdate);
|
|
||||||
|
|
||||||
// has the item modified today?
|
|
||||||
if (lastUpdateStr.equals(today)) {
|
|
||||||
List<MetadataValue> dateAccArr = itemService.getMetadata(infoObject.item, "dc",
|
|
||||||
"date", "accessioned", Item.ANY);
|
|
||||||
// we need only the item archived yesterday
|
|
||||||
if (dateAccArr != null && dateAccArr.size() > 0) {
|
|
||||||
for (MetadataValue date : dateAccArr) {
|
|
||||||
if (date != null && date.getValue() != null) {
|
|
||||||
// if it hasn't been archived today
|
|
||||||
if (date.getValue().startsWith(yesterday)) {
|
|
||||||
filteredList.add(infoObject);
|
|
||||||
log.debug("adding : " + dateAccArr.get(0).getValue()
|
|
||||||
+ " : " + today + " : "
|
|
||||||
+ infoObject.handle);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
log.debug("ignoring : " + dateAccArr.get(0).getValue()
|
|
||||||
+ " : " + today + " : "
|
|
||||||
+ infoObject.handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.debug("no date accessioned, adding : "
|
|
||||||
+ infoObject.handle);
|
|
||||||
filteredList.add(infoObject);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// the item has been modified yesterday...
|
|
||||||
filteredList.add(infoObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<HarvestedItemInfo> filterOutModified(List<HarvestedItemInfo> completeList) {
|
|
||||||
log.debug("Filtering out all modified to leave new items list size=" + completeList.size());
|
|
||||||
List<HarvestedItemInfo> filteredList = new ArrayList<>();
|
|
||||||
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
|
||||||
// Get the start and end dates for yesterday
|
|
||||||
Date thisTimeYesterday = new Date(System.currentTimeMillis()
|
|
||||||
- (24 * 60 * 60 * 1000));
|
|
||||||
String yesterday = sdf.format(thisTimeYesterday);
|
|
||||||
|
|
||||||
for (HarvestedItemInfo infoObject : completeList) {
|
|
||||||
List<MetadataValue> dateAccArr = itemService
|
|
||||||
.getMetadata(infoObject.item, "dc", "date", "accessioned", Item.ANY);
|
|
||||||
|
|
||||||
if (dateAccArr != null && dateAccArr.size() > 0) {
|
|
||||||
for (MetadataValue date : dateAccArr) {
|
|
||||||
if (date != null && date.getValue() != null) {
|
|
||||||
// if it has been archived yesterday
|
|
||||||
if (date.getValue().startsWith(yesterday)) {
|
|
||||||
filteredList.add(infoObject);
|
|
||||||
log.debug("adding : " + dateAccArr.get(0)
|
|
||||||
.getValue() + " : " + yesterday + " : " + infoObject
|
|
||||||
.handle);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
log.debug("ignoring : " + dateAccArr.get(0)
|
|
||||||
.getValue() + " : " + yesterday + " : " + infoObject
|
|
||||||
.handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
log.debug("no date accessioned, adding : " + infoObject.handle);
|
|
||||||
filteredList.add(infoObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredList;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -9,11 +9,16 @@ package org.dspace.eperson;
|
|||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.authorize.service.AuthorizeService;
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.content.service.CollectionService;
|
import org.dspace.content.service.CollectionService;
|
||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
@@ -29,106 +34,177 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
* @version $Revision$
|
* @version $Revision$
|
||||||
*/
|
*/
|
||||||
public class SubscribeServiceImpl implements SubscribeService {
|
public class SubscribeServiceImpl implements SubscribeService {
|
||||||
/**
|
|
||||||
* log4j logger
|
private Logger log = LogManager.getLogger(SubscribeServiceImpl.class);
|
||||||
*/
|
|
||||||
private Logger log = org.apache.logging.log4j.LogManager.getLogger(SubscribeServiceImpl.class);
|
|
||||||
|
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected SubscriptionDAO subscriptionDAO;
|
private SubscriptionDAO subscriptionDAO;
|
||||||
|
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected AuthorizeService authorizeService;
|
private AuthorizeService authorizeService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected CollectionService collectionService;
|
private CollectionService collectionService;
|
||||||
|
|
||||||
protected SubscribeServiceImpl() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Subscription> findAll(Context context) throws SQLException {
|
public List<Subscription> findAll(Context context, String resourceType, Integer limit, Integer offset)
|
||||||
return subscriptionDAO.findAllOrderedByEPerson(context);
|
throws Exception {
|
||||||
}
|
if (StringUtils.isBlank(resourceType)) {
|
||||||
|
return subscriptionDAO.findAllOrderedByDSO(context, limit, offset);
|
||||||
@Override
|
|
||||||
public void subscribe(Context context, EPerson eperson,
|
|
||||||
Collection collection) throws SQLException, AuthorizeException {
|
|
||||||
// Check authorisation. Must be administrator, or the eperson.
|
|
||||||
if (authorizeService.isAdmin(context)
|
|
||||||
|| ((context.getCurrentUser() != null) && (context
|
|
||||||
.getCurrentUser().getID().equals(eperson.getID())))) {
|
|
||||||
if (!isSubscribed(context, eperson, collection)) {
|
|
||||||
Subscription subscription = subscriptionDAO.create(context, new Subscription());
|
|
||||||
subscription.setCollection(collection);
|
|
||||||
subscription.setePerson(eperson);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
throw new AuthorizeException(
|
if (resourceType.equals(Collection.class.getSimpleName()) ||
|
||||||
"Only admin or e-person themselves can subscribe");
|
resourceType.equals(Community.class.getSimpleName())) {
|
||||||
|
return subscriptionDAO.findAllOrderedByIDAndResourceType(context, resourceType, limit, offset);
|
||||||
|
} else {
|
||||||
|
log.error("Resource type must be Collection or Community");
|
||||||
|
throw new Exception("Resource type must be Collection or Community");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unsubscribe(Context context, EPerson eperson,
|
public Subscription subscribe(Context context, EPerson eperson,
|
||||||
Collection collection) throws SQLException, AuthorizeException {
|
DSpaceObject dSpaceObject,
|
||||||
|
List<SubscriptionParameter> subscriptionParameterList,
|
||||||
|
String type) throws SQLException, AuthorizeException {
|
||||||
// Check authorisation. Must be administrator, or the eperson.
|
// Check authorisation. Must be administrator, or the eperson.
|
||||||
if (authorizeService.isAdmin(context)
|
if (authorizeService.isAdmin(context)
|
||||||
|| ((context.getCurrentUser() != null) && (context
|
|| ((context.getCurrentUser() != null) && (context
|
||||||
.getCurrentUser().getID().equals(eperson.getID())))) {
|
.getCurrentUser().getID().equals(eperson.getID())))) {
|
||||||
if (collection == null) {
|
Subscription newSubscription = subscriptionDAO.create(context, new Subscription());
|
||||||
|
subscriptionParameterList.forEach(subscriptionParameter ->
|
||||||
|
newSubscription.addParameter(subscriptionParameter));
|
||||||
|
newSubscription.setEPerson(eperson);
|
||||||
|
newSubscription.setDSpaceObject(dSpaceObject);
|
||||||
|
newSubscription.setSubscriptionType(type);
|
||||||
|
return newSubscription;
|
||||||
|
} else {
|
||||||
|
throw new AuthorizeException("Only admin or e-person themselves can subscribe");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unsubscribe(Context context, EPerson eperson, DSpaceObject dSpaceObject)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
// Check authorisation. Must be administrator, or the eperson.
|
||||||
|
if (authorizeService.isAdmin(context)
|
||||||
|
|| ((context.getCurrentUser() != null) && (context
|
||||||
|
.getCurrentUser().getID().equals(eperson.getID())))) {
|
||||||
|
if (dSpaceObject == null) {
|
||||||
// Unsubscribe from all
|
// Unsubscribe from all
|
||||||
subscriptionDAO.deleteByEPerson(context, eperson);
|
subscriptionDAO.deleteByEPerson(context, eperson);
|
||||||
} else {
|
} else {
|
||||||
subscriptionDAO.deleteByCollectionAndEPerson(context, collection, eperson);
|
subscriptionDAO.deleteByDSOAndEPerson(context, dSpaceObject, eperson);
|
||||||
|
|
||||||
log.info(LogHelper.getHeader(context, "unsubscribe",
|
log.info(LogHelper.getHeader(context, "unsubscribe",
|
||||||
"eperson_id=" + eperson.getID() + ",collection_id="
|
"eperson_id=" + eperson.getID() + ",collection_id="
|
||||||
+ collection.getID()));
|
+ dSpaceObject.getID()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new AuthorizeException(
|
throw new AuthorizeException("Only admin or e-person themselves can unsubscribe");
|
||||||
"Only admin or e-person themselves can unsubscribe");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Subscription> getSubscriptions(Context context, EPerson eperson)
|
public List<Subscription> findSubscriptionsByEPerson(Context context, EPerson eperson, Integer limit,Integer offset)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return subscriptionDAO.findByEPerson(context, eperson);
|
return subscriptionDAO.findByEPerson(context, eperson, limit, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Collection> getAvailableSubscriptions(Context context)
|
public List<Subscription> findSubscriptionsByEPersonAndDso(Context context, EPerson eperson,
|
||||||
throws SQLException {
|
DSpaceObject dSpaceObject,
|
||||||
return getAvailableSubscriptions(context, null);
|
Integer limit, Integer offset) throws SQLException {
|
||||||
|
return subscriptionDAO.findByEPersonAndDso(context, eperson, dSpaceObject, limit, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Collection> getAvailableSubscriptions(Context context, EPerson eperson)
|
public List<Collection> findAvailableSubscriptions(Context context) throws SQLException {
|
||||||
throws SQLException {
|
return findAvailableSubscriptions(context, null);
|
||||||
List<Collection> collections;
|
}
|
||||||
if (eperson != null) {
|
|
||||||
|
@Override
|
||||||
|
public List<Collection> findAvailableSubscriptions(Context context, EPerson eperson) throws SQLException {
|
||||||
|
if (Objects.nonNull(eperson)) {
|
||||||
context.setCurrentUser(eperson);
|
context.setCurrentUser(eperson);
|
||||||
}
|
}
|
||||||
collections = collectionService.findAuthorized(context, null, Constants.ADD);
|
return collectionService.findAuthorized(context, null, Constants.ADD);
|
||||||
|
|
||||||
return collections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSubscribed(Context context, EPerson eperson,
|
public boolean isSubscribed(Context context, EPerson eperson, DSpaceObject dSpaceObject) throws SQLException {
|
||||||
Collection collection) throws SQLException {
|
return subscriptionDAO.findByEPersonAndDso(context, eperson, dSpaceObject, -1, -1) != null;
|
||||||
return subscriptionDAO.findByCollectionAndEPerson(context, eperson, collection) != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteByCollection(Context context, Collection collection) throws SQLException {
|
public void deleteByDspaceObject(Context context, DSpaceObject dSpaceObject) throws SQLException {
|
||||||
subscriptionDAO.deleteByCollection(context, collection);
|
subscriptionDAO.deleteByDspaceObject(context, dSpaceObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException {
|
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException {
|
||||||
subscriptionDAO.deleteByEPerson(context, ePerson);
|
subscriptionDAO.deleteByEPerson(context, ePerson);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Subscription findById(Context context, int id) throws SQLException {
|
||||||
|
return subscriptionDAO.findByID(context, Subscription.class, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Subscription updateSubscription(Context context, Integer id, String subscriptionType,
|
||||||
|
List<SubscriptionParameter> subscriptionParameterList)
|
||||||
|
throws SQLException {
|
||||||
|
Subscription subscriptionDB = subscriptionDAO.findByID(context, Subscription.class, id);
|
||||||
|
subscriptionDB.removeParameterList();
|
||||||
|
subscriptionDB.setSubscriptionType(subscriptionType);
|
||||||
|
subscriptionParameterList.forEach(x -> subscriptionDB.addParameter(x));
|
||||||
|
subscriptionDAO.save(context, subscriptionDB);
|
||||||
|
return subscriptionDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Subscription addSubscriptionParameter(Context context, Integer id, SubscriptionParameter subscriptionParam)
|
||||||
|
throws SQLException {
|
||||||
|
Subscription subscriptionDB = subscriptionDAO.findByID(context, Subscription.class, id);
|
||||||
|
subscriptionDB.addParameter(subscriptionParam);
|
||||||
|
subscriptionDAO.save(context, subscriptionDB);
|
||||||
|
return subscriptionDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Subscription removeSubscriptionParameter(Context context,Integer id, SubscriptionParameter subscriptionParam)
|
||||||
|
throws SQLException {
|
||||||
|
Subscription subscriptionDB = subscriptionDAO.findByID(context, Subscription.class, id);
|
||||||
|
subscriptionDB.removeParameter(subscriptionParam);
|
||||||
|
subscriptionDAO.save(context, subscriptionDB);
|
||||||
|
return subscriptionDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteSubscription(Context context, Subscription subscription) throws SQLException {
|
||||||
|
subscriptionDAO.delete(context, subscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Subscription> findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
|
||||||
|
String subscriptionType, String frequencyValue) throws SQLException {
|
||||||
|
return subscriptionDAO.findAllSubscriptionsBySubscriptionTypeAndFrequency(context, subscriptionType,
|
||||||
|
frequencyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long countAll(Context context) throws SQLException {
|
||||||
|
return subscriptionDAO.countAll(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long countSubscriptionsByEPerson(Context context, EPerson ePerson) throws SQLException {
|
||||||
|
return subscriptionDAO.countAllByEPerson(context, ePerson);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long countByEPersonAndDSO(Context context, EPerson ePerson, DSpaceObject dSpaceObject)
|
||||||
|
throws SQLException {
|
||||||
|
return subscriptionDAO.countAllByEPersonAndDso(context, ePerson, dSpaceObject);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.eperson;
|
package org.dspace.eperson;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
@@ -15,10 +18,11 @@ import javax.persistence.GenerationType;
|
|||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.SequenceGenerator;
|
import javax.persistence.SequenceGenerator;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.ReloadableEntity;
|
import org.dspace.core.ReloadableEntity;
|
||||||
|
|
||||||
@@ -37,40 +41,78 @@ public class Subscription implements ReloadableEntity<Integer> {
|
|||||||
@SequenceGenerator(name = "subscription_seq", sequenceName = "subscription_seq", allocationSize = 1)
|
@SequenceGenerator(name = "subscription_seq", sequenceName = "subscription_seq", allocationSize = 1)
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
@JoinColumn(name = "collection_id")
|
@JoinColumn(name = "dspace_object_id")
|
||||||
private Collection collection;
|
private DSpaceObject dSpaceObject;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "eperson_id")
|
@JoinColumn(name = "eperson_id")
|
||||||
private EPerson ePerson;
|
private EPerson ePerson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protected constructor, create object using:
|
* Represent subscription type, for example, "content" or "statistics".
|
||||||
* {@link org.dspace.eperson.service.SubscribeService#subscribe(Context, EPerson, Collection)}
|
*
|
||||||
|
* NOTE: Currently, in DSpace we use only one "content"
|
||||||
*/
|
*/
|
||||||
protected Subscription() {
|
@Column(name = "type")
|
||||||
|
private String subscriptionType;
|
||||||
|
|
||||||
}
|
@OneToMany(fetch = FetchType.LAZY, mappedBy = "subscription", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
private List<SubscriptionParameter> subscriptionParameterList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protected constructor, create object using:
|
||||||
|
* {@link org.dspace.eperson.service.SubscribeService#subscribe(Context, EPerson, DSpaceObject, List, String)}
|
||||||
|
*/
|
||||||
|
protected Subscription() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer getID() {
|
public Integer getID() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getCollection() {
|
public DSpaceObject getDSpaceObject() {
|
||||||
return collection;
|
return this.dSpaceObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCollection(Collection collection) {
|
void setDSpaceObject(DSpaceObject dSpaceObject) {
|
||||||
this.collection = collection;
|
this.dSpaceObject = dSpaceObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EPerson getePerson() {
|
public EPerson getEPerson() {
|
||||||
return ePerson;
|
return ePerson;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setePerson(EPerson ePerson) {
|
public void setEPerson(EPerson ePerson) {
|
||||||
this.ePerson = ePerson;
|
this.ePerson = ePerson;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public String getSubscriptionType() {
|
||||||
|
return subscriptionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubscriptionType(String subscriptionType) {
|
||||||
|
this.subscriptionType = subscriptionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SubscriptionParameter> getSubscriptionParameterList() {
|
||||||
|
return subscriptionParameterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubscriptionParameterList(List<SubscriptionParameter> subscriptionList) {
|
||||||
|
this.subscriptionParameterList = subscriptionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addParameter(SubscriptionParameter subscriptionParameter) {
|
||||||
|
subscriptionParameterList.add(subscriptionParameter);
|
||||||
|
subscriptionParameter.setSubscription(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeParameterList() {
|
||||||
|
subscriptionParameterList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeParameter(SubscriptionParameter subscriptionParameter) {
|
||||||
|
subscriptionParameterList.remove(subscriptionParameter);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* 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.eperson;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.SequenceGenerator;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.dspace.core.ReloadableEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database entity representation of the subscription_parameter table
|
||||||
|
* SubscriptionParameter represents a frequency with which an user wants to be notified.
|
||||||
|
*
|
||||||
|
* @author Alba Aliu at atis.al
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "subscription_parameter")
|
||||||
|
public class SubscriptionParameter implements ReloadableEntity<Integer> {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "subscription_parameter_seq")
|
||||||
|
@SequenceGenerator(name = "subscription_parameter_seq", sequenceName = "subscription_parameter_seq",
|
||||||
|
allocationSize = 1)
|
||||||
|
@Column(name = "subscription_parameter_id", unique = true)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "subscription_id", nullable = false)
|
||||||
|
private Subscription subscription;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently, we have only one use case for this attribute: "frequency"
|
||||||
|
*/
|
||||||
|
@Column
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently, we use this attribute only with following values: "D", "W", "M".
|
||||||
|
* Where D stand for Day, W stand for Week and M stand for Month
|
||||||
|
*/
|
||||||
|
@Column
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public SubscriptionParameter() {}
|
||||||
|
|
||||||
|
public SubscriptionParameter(Integer id, Subscription subscription, String name, String value) {
|
||||||
|
this.id = id;
|
||||||
|
this.subscription = subscription;
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Subscription getSubscription() {
|
||||||
|
return subscription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubscription(Subscription subscription) {
|
||||||
|
this.subscription = subscription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -10,7 +10,7 @@ package org.dspace.eperson.dao;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.GenericDAO;
|
import org.dspace.core.GenericDAO;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
@@ -26,17 +26,125 @@ import org.dspace.eperson.Subscription;
|
|||||||
*/
|
*/
|
||||||
public interface SubscriptionDAO extends GenericDAO<Subscription> {
|
public interface SubscriptionDAO extends GenericDAO<Subscription> {
|
||||||
|
|
||||||
public void deleteByCollection(Context context, Collection collection) throws SQLException;
|
/**
|
||||||
|
* Delete all subscription of provided dSpaceObject
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param dSpaceObject DSpace resource
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public void deleteByDspaceObject(Context context, DSpaceObject dSpaceObject) throws SQLException;
|
||||||
|
|
||||||
public List<Subscription> findByEPerson(Context context, EPerson eperson) throws SQLException;
|
/**
|
||||||
|
* Return a paginated list of all subscriptions of the eperson
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param eperson ePerson whose subscriptions want to find
|
||||||
|
* @param limit Paging limit
|
||||||
|
* @param offset The position of the first result to return
|
||||||
|
* @return
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public List<Subscription> findByEPerson(Context context, EPerson eperson, Integer limit, Integer offset)
|
||||||
|
throws SQLException;
|
||||||
|
|
||||||
public Subscription findByCollectionAndEPerson(Context context, EPerson eperson, Collection collection)
|
/**
|
||||||
throws SQLException;
|
* Return a paginated list of subscriptions related to a DSpaceObject belong to an ePerson
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param eperson ePerson whose subscriptions want to find
|
||||||
|
* @param dSpaceObject DSpaceObject of whom subscriptions want to find
|
||||||
|
* @param limit Paging limit
|
||||||
|
* @param offset The position of the first result to return
|
||||||
|
* @return
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public List<Subscription> findByEPersonAndDso(Context context, EPerson eperson, DSpaceObject dSpaceObject,
|
||||||
|
Integer limit, Integer offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all subscription of provided ePerson
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param eperson ePerson whose subscriptions want to delete
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
public void deleteByEPerson(Context context, EPerson eperson) throws SQLException;
|
public void deleteByEPerson(Context context, EPerson eperson) throws SQLException;
|
||||||
|
|
||||||
public void deleteByCollectionAndEPerson(Context context, Collection collection, EPerson eperson)
|
/**
|
||||||
throws SQLException;
|
* Delete all subscriptions related to a DSpaceObject belong to an ePerson
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param dSpaceObject DSpaceObject of whom subscriptions want to delete
|
||||||
|
* @param eperson ePerson whose subscriptions want to delete
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public void deleteByDSOAndEPerson(Context context, DSpaceObject dSpaceObject, EPerson eperson) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a paginated list of all subscriptions ordered by ID and resourceType
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param resourceType Could be Collection or Community
|
||||||
|
* @param limit Paging limit
|
||||||
|
* @param offset The position of the first result to return
|
||||||
|
* @return
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public List<Subscription> findAllOrderedByIDAndResourceType(Context context, String resourceType,
|
||||||
|
Integer limit, Integer offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a paginated list of subscriptions ordered by DSpaceObject
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param limit Paging limit
|
||||||
|
* @param offset The position of the first result to return
|
||||||
|
* @return
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public List<Subscription> findAllOrderedByDSO(Context context, Integer limit, Integer offset) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a list of all subscriptions by subscriptionType and frequency
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param subscriptionType Could be "content" or "statistics". NOTE: in DSpace we have only "content"
|
||||||
|
* @param frequencyValue Could be "D" stand for Day, "W" stand for Week, and "M" stand for Month
|
||||||
|
* @return
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public List<Subscription> findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
|
||||||
|
String subscriptionType, String frequencyValue) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count all subscriptions
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @return Total of all subscriptions
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public Long countAll(Context context) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count all subscriptions belong to an ePerson
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param ePerson ePerson whose subscriptions want count
|
||||||
|
* @return Total of all subscriptions belong to an ePerson
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public Long countAllByEPerson(Context context, EPerson ePerson) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count all subscriptions related to a DSpaceObject belong to an ePerson
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param ePerson ePerson whose subscriptions want count
|
||||||
|
* @param dSpaceObject DSpaceObject of whom subscriptions want count
|
||||||
|
* @return
|
||||||
|
* @throws SQLException If database error
|
||||||
|
*/
|
||||||
|
public Long countAllByEPersonAndDso(Context context, EPerson ePerson,DSpaceObject dSpaceObject) throws SQLException;
|
||||||
|
|
||||||
public List<Subscription> findAllOrderedByEPerson(Context context) throws SQLException;
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 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.eperson.dao;
|
||||||
|
import org.dspace.core.GenericDAO;
|
||||||
|
import org.dspace.eperson.SubscriptionParameter;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database Access Object interface class for the SubscriptionParamter object.
|
||||||
|
* The implementation of this class is responsible for all database calls for the SubscriptionParameter object and is
|
||||||
|
* autowired by spring
|
||||||
|
* This class should only be accessed from a single service and should never be exposed outside of the API
|
||||||
|
*
|
||||||
|
* @author Alba Aliu at atis.al
|
||||||
|
*/
|
||||||
|
public interface SubscriptionParameterDAO extends GenericDAO<SubscriptionParameter> {
|
||||||
|
}
|
@@ -9,17 +9,21 @@ package org.dspace.eperson.dao.impl;
|
|||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Join;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.core.AbstractHibernateDAO;
|
import org.dspace.core.AbstractHibernateDAO;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Subscription;
|
import org.dspace.eperson.Subscription;
|
||||||
|
import org.dspace.eperson.SubscriptionParameter;
|
||||||
|
import org.dspace.eperson.SubscriptionParameter_;
|
||||||
import org.dspace.eperson.Subscription_;
|
import org.dspace.eperson.Subscription_;
|
||||||
import org.dspace.eperson.dao.SubscriptionDAO;
|
import org.dspace.eperson.dao.SubscriptionDAO;
|
||||||
|
|
||||||
@@ -31,42 +35,50 @@ import org.dspace.eperson.dao.SubscriptionDAO;
|
|||||||
* @author kevinvandevelde at atmire.com
|
* @author kevinvandevelde at atmire.com
|
||||||
*/
|
*/
|
||||||
public class SubscriptionDAOImpl extends AbstractHibernateDAO<Subscription> implements SubscriptionDAO {
|
public class SubscriptionDAOImpl extends AbstractHibernateDAO<Subscription> implements SubscriptionDAO {
|
||||||
|
|
||||||
protected SubscriptionDAOImpl() {
|
protected SubscriptionDAOImpl() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Subscription> findByEPerson(Context context, EPerson eperson) throws SQLException {
|
public List<Subscription> findByEPerson(Context context, EPerson eperson, Integer limit, Integer offset)
|
||||||
|
throws SQLException {
|
||||||
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||||
javax.persistence.criteria.CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class);
|
javax.persistence.criteria.CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class);
|
||||||
Root<Subscription> subscriptionRoot = criteriaQuery.from(Subscription.class);
|
Root<Subscription> subscriptionRoot = criteriaQuery.from(Subscription.class);
|
||||||
criteriaQuery.select(subscriptionRoot);
|
criteriaQuery.select(subscriptionRoot);
|
||||||
criteriaQuery.where(criteriaBuilder.equal(subscriptionRoot.get(Subscription_.ePerson), eperson));
|
criteriaQuery.where(criteriaBuilder.equal(subscriptionRoot.get(Subscription_.ePerson), eperson));
|
||||||
return list(context, criteriaQuery, false, Subscription.class, -1, -1);
|
List<javax.persistence.criteria.Order> orderList = new LinkedList<>();
|
||||||
|
orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.dSpaceObject)));
|
||||||
|
criteriaQuery.orderBy(orderList);
|
||||||
|
return list(context, criteriaQuery, false, Subscription.class, limit, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Subscription findByCollectionAndEPerson(Context context, EPerson eperson, Collection collection)
|
public List<Subscription> findByEPersonAndDso(Context context, EPerson eperson,
|
||||||
throws SQLException {
|
DSpaceObject dSpaceObject,
|
||||||
|
Integer limit, Integer offset) throws SQLException {
|
||||||
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||||
javax.persistence.criteria.CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class);
|
javax.persistence.criteria.CriteriaQuery criteriaQuery =
|
||||||
|
getCriteriaQuery(criteriaBuilder, Subscription.class);
|
||||||
Root<Subscription> subscriptionRoot = criteriaQuery.from(Subscription.class);
|
Root<Subscription> subscriptionRoot = criteriaQuery.from(Subscription.class);
|
||||||
criteriaQuery.select(subscriptionRoot);
|
criteriaQuery.select(subscriptionRoot);
|
||||||
criteriaQuery
|
criteriaQuery.where(criteriaBuilder.and(criteriaBuilder.equal(
|
||||||
.where(criteriaBuilder.and(criteriaBuilder.equal(subscriptionRoot.get(Subscription_.ePerson), eperson),
|
subscriptionRoot.get(Subscription_.ePerson), eperson),
|
||||||
criteriaBuilder.equal(subscriptionRoot.get(Subscription_.collection), collection)
|
criteriaBuilder.equal(subscriptionRoot.get(Subscription_.dSpaceObject), dSpaceObject)
|
||||||
)
|
));
|
||||||
);
|
List<javax.persistence.criteria.Order> orderList = new LinkedList<>();
|
||||||
return singleResult(context, criteriaQuery);
|
orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.dSpaceObject)));
|
||||||
|
criteriaQuery.orderBy(orderList);
|
||||||
|
return list(context, criteriaQuery, false, Subscription.class, limit, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteByCollection(Context context, Collection collection) throws SQLException {
|
public void deleteByDspaceObject(Context context, DSpaceObject dSpaceObject) throws SQLException {
|
||||||
String hqlQuery = "delete from Subscription where collection=:collection";
|
String hqlQuery = "delete from Subscription where dSpaceObject=:dSpaceObject";
|
||||||
Query query = createQuery(context, hqlQuery);
|
Query query = createQuery(context, hqlQuery);
|
||||||
query.setParameter("collection", collection);
|
query.setParameter("dSpaceObject", dSpaceObject);
|
||||||
query.executeUpdate();
|
query.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,28 +91,98 @@ public class SubscriptionDAOImpl extends AbstractHibernateDAO<Subscription> impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteByCollectionAndEPerson(Context context, Collection collection, EPerson eperson)
|
public void deleteByDSOAndEPerson(Context context, DSpaceObject dSpaceObject, EPerson eperson)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
String hqlQuery = "delete from Subscription where collection=:collection AND ePerson=:ePerson";
|
String hqlQuery = "delete from Subscription where dSpaceObject=:dSpaceObject AND ePerson=:ePerson";
|
||||||
Query query = createQuery(context, hqlQuery);
|
Query query = createQuery(context, hqlQuery);
|
||||||
query.setParameter("collection", collection);
|
query.setParameter("dSpaceObject", dSpaceObject);
|
||||||
query.setParameter("ePerson", eperson);
|
query.setParameter("ePerson", eperson);
|
||||||
query.executeUpdate();
|
query.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Subscription> findAllOrderedByEPerson(Context context) throws SQLException {
|
public List<Subscription> findAllOrderedByIDAndResourceType(Context context, String resourceType,
|
||||||
|
Integer limit, Integer offset) throws SQLException {
|
||||||
|
String hqlQuery = "select s from Subscription s join %s dso " +
|
||||||
|
"ON dso.id = s.dSpaceObject ORDER BY subscription_id";
|
||||||
|
if (resourceType != null) {
|
||||||
|
hqlQuery = String.format(hqlQuery, resourceType);
|
||||||
|
}
|
||||||
|
Query query = createQuery(context, hqlQuery);
|
||||||
|
if (limit != -1) {
|
||||||
|
query.setMaxResults(limit);
|
||||||
|
}
|
||||||
|
if (offset != -1) {
|
||||||
|
query.setFirstResult(offset);
|
||||||
|
}
|
||||||
|
query.setHint("org.hibernate.cacheable", false);
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Subscription> findAllOrderedByDSO(Context context, Integer limit, Integer offset) throws SQLException {
|
||||||
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||||
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class);
|
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class);
|
||||||
Root<Subscription> subscriptionRoot = criteriaQuery.from(Subscription.class);
|
Root<Subscription> subscriptionRoot = criteriaQuery.from(Subscription.class);
|
||||||
criteriaQuery.select(subscriptionRoot);
|
criteriaQuery.select(subscriptionRoot);
|
||||||
|
List<javax.persistence.criteria.Order> orderList = new LinkedList<>();
|
||||||
|
orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.dSpaceObject)));
|
||||||
|
criteriaQuery.orderBy(orderList);
|
||||||
|
return list(context, criteriaQuery, false, Subscription.class, limit, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Subscription> findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
|
||||||
|
String subscriptionType, String frequencyValue) throws SQLException {
|
||||||
|
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||||
|
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class);
|
||||||
|
Root<Subscription> subscriptionRoot = criteriaQuery.from(Subscription.class);
|
||||||
|
criteriaQuery.select(subscriptionRoot);
|
||||||
|
Join<Subscription, SubscriptionParameter> childJoin = subscriptionRoot.join("subscriptionParameterList");
|
||||||
|
criteriaQuery.where(
|
||||||
|
criteriaBuilder.and(
|
||||||
|
criteriaBuilder.equal(subscriptionRoot.get(Subscription_.SUBSCRIPTION_TYPE), subscriptionType),
|
||||||
|
criteriaBuilder.equal(childJoin.get(SubscriptionParameter_.name), "frequency"),
|
||||||
|
criteriaBuilder.equal(childJoin.get(SubscriptionParameter_.value), frequencyValue)
|
||||||
|
));
|
||||||
List<javax.persistence.criteria.Order> orderList = new ArrayList<>(1);
|
List<javax.persistence.criteria.Order> orderList = new ArrayList<>(1);
|
||||||
orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.ePerson)));
|
orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.ePerson)));
|
||||||
|
orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.id)));
|
||||||
criteriaQuery.orderBy(orderList);
|
criteriaQuery.orderBy(orderList);
|
||||||
|
return list(context, criteriaQuery, false, Subscription.class, 10000, -1);
|
||||||
return list(context, criteriaQuery, false, Subscription.class, -1, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long countAll(Context context) throws SQLException {
|
||||||
|
CriteriaBuilder qb = getCriteriaBuilder(context);
|
||||||
|
CriteriaQuery<Long> cq = qb.createQuery(Long.class);
|
||||||
|
cq.select(qb.count(cq.from(Subscription.class)));
|
||||||
|
Query query = this.getHibernateSession(context).createQuery(cq);
|
||||||
|
return (Long) query.getSingleResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long countAllByEPerson(Context context, EPerson ePerson) throws SQLException {
|
||||||
|
CriteriaBuilder qb = getCriteriaBuilder(context);
|
||||||
|
CriteriaQuery<Long> cq = qb.createQuery(Long.class);
|
||||||
|
Root<Subscription> subscriptionRoot = cq.from(Subscription.class);
|
||||||
|
cq.select(qb.count(subscriptionRoot));
|
||||||
|
cq.where(qb.equal(subscriptionRoot.get(Subscription_.ePerson), ePerson));
|
||||||
|
Query query = this.getHibernateSession(context).createQuery(cq);
|
||||||
|
return (Long) query.getSingleResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long countAllByEPersonAndDso(Context context,
|
||||||
|
EPerson ePerson, DSpaceObject dSpaceObject) throws SQLException {
|
||||||
|
CriteriaBuilder qb = getCriteriaBuilder(context);
|
||||||
|
CriteriaQuery<Long> cq = qb.createQuery(Long.class);
|
||||||
|
Root<Subscription> subscriptionRoot = cq.from(Subscription.class);
|
||||||
|
cq.select(qb.count(subscriptionRoot));
|
||||||
|
cq.where(qb.and(qb.equal(subscriptionRoot.get(Subscription_.ePerson)
|
||||||
|
, ePerson), qb.equal(subscriptionRoot.get(Subscription_.dSpaceObject), dSpaceObject)));
|
||||||
|
Query query = this.getHibernateSession(context).createQuery(cq);
|
||||||
|
return (Long) query.getSingleResult();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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.eperson.dao.impl;
|
||||||
|
|
||||||
|
import org.dspace.core.AbstractHibernateDAO;
|
||||||
|
import org.dspace.eperson.SubscriptionParameter;
|
||||||
|
import org.dspace.eperson.dao.SubscriptionParameterDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hibernate implementation of the Database Access Object interface class for the SubscriptionParameter object.
|
||||||
|
* This class is responsible for all database calls for the SubscriptionParameter object and is autowired by spring
|
||||||
|
* This class should never be accessed directly.
|
||||||
|
*
|
||||||
|
* @author Alba Aliu at atis.al
|
||||||
|
*/
|
||||||
|
public class SubscriptionParameterDAOImpl extends AbstractHibernateDAO<SubscriptionParameter>
|
||||||
|
implements SubscriptionParameterDAO {
|
||||||
|
|
||||||
|
protected SubscriptionParameterDAOImpl() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -12,9 +12,11 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Subscription;
|
import org.dspace.eperson.Subscription;
|
||||||
|
import org.dspace.eperson.SubscriptionParameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service interface class for the Subscription object.
|
* Service interface class for the Subscription object.
|
||||||
@@ -31,49 +33,74 @@ public interface SubscribeService {
|
|||||||
* new item appears in the collection.
|
* new item appears in the collection.
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
|
* @param limit Number of subscriptions to return
|
||||||
|
* @param offset Offset number
|
||||||
* @return list of Subscription objects
|
* @return list of Subscription objects
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public List<Subscription> findAll(Context context) throws SQLException;
|
public List<Subscription> findAll(Context context, String resourceType, Integer limit, Integer offset)
|
||||||
|
throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribe an e-person to a collection. An e-mail will be sent every day a
|
* Subscribe an EPerson to a dSpaceObject (Collection or Community). An e-mail will be sent every day a
|
||||||
* new item appears in the collection.
|
* new item appears in the Collection or Community.
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context object
|
||||||
* @param eperson EPerson to subscribe
|
* @param eperson EPerson to subscribe
|
||||||
* @param collection Collection to subscribe to
|
* @param dSpaceObject DSpaceObject to subscribe
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @param subscriptionParameters list of @SubscriptionParameter
|
||||||
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
* @param subscriptionType Currently supported only "content"
|
||||||
* to perform a particular action.
|
* @return
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
||||||
|
* to perform a particular action.
|
||||||
*/
|
*/
|
||||||
public void subscribe(Context context, EPerson eperson,
|
public Subscription subscribe(Context context, EPerson eperson, DSpaceObject dSpaceObject,
|
||||||
Collection collection) throws SQLException, AuthorizeException;
|
List<SubscriptionParameter> subscriptionParameters,
|
||||||
|
String subscriptionType) throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsubscribe an e-person to a collection. Passing in <code>null</code>
|
* Unsubscribe an e-person to a collection. Passing in <code>null</code>
|
||||||
* for the collection unsubscribes the e-person from all collections they
|
* for the collection unsubscribes the e-person from all collections they
|
||||||
* are subscribed to.
|
* are subscribed to.
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
* @param eperson EPerson to unsubscribe
|
* @param eperson EPerson to unsubscribe
|
||||||
* @param collection Collection to unsubscribe from
|
* @param dSpaceObject DSpaceObject to unsubscribe from
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
|
||||||
* to perform a particular action.
|
* to perform a particular action.
|
||||||
*/
|
*/
|
||||||
public void unsubscribe(Context context, EPerson eperson,
|
public void unsubscribe(Context context, EPerson eperson, DSpaceObject dSpaceObject)
|
||||||
Collection collection) throws SQLException, AuthorizeException;
|
throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find out which collections an e-person is subscribed to
|
* Find out which collections an e-person is subscribed to
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
* @param eperson EPerson
|
* @param eperson EPerson
|
||||||
|
* @param limit Number of subscriptions to return
|
||||||
|
* @param offset Offset number
|
||||||
* @return array of collections e-person is subscribed to
|
* @return array of collections e-person is subscribed to
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public List<Subscription> getSubscriptions(Context context, EPerson eperson) throws SQLException;
|
public List<Subscription> findSubscriptionsByEPerson(Context context, EPerson eperson, Integer limit,Integer offset)
|
||||||
|
throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find out which collections an e-person is subscribed to and related with dso
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param eperson EPerson
|
||||||
|
* @param dSpaceObject DSpaceObject
|
||||||
|
* @param limit Number of subscriptions to return
|
||||||
|
* @param offset Offset number
|
||||||
|
* @return array of collections e-person is subscribed to and related with dso
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
public List<Subscription> findSubscriptionsByEPersonAndDso(Context context, EPerson eperson,
|
||||||
|
DSpaceObject dSpaceObject,
|
||||||
|
Integer limit, Integer offset) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find out which collections the currently logged in e-person can subscribe to
|
* Find out which collections the currently logged in e-person can subscribe to
|
||||||
@@ -82,8 +109,7 @@ public interface SubscribeService {
|
|||||||
* @return array of collections the currently logged in e-person can subscribe to
|
* @return array of collections the currently logged in e-person can subscribe to
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public List<Collection> getAvailableSubscriptions(Context context)
|
public List<Collection> findAvailableSubscriptions(Context context) throws SQLException;
|
||||||
throws SQLException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find out which collections an e-person can subscribe to
|
* Find out which collections an e-person can subscribe to
|
||||||
@@ -93,29 +119,27 @@ public interface SubscribeService {
|
|||||||
* @return array of collections e-person can subscribe to
|
* @return array of collections e-person can subscribe to
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public List<Collection> getAvailableSubscriptions(Context context, EPerson eperson)
|
public List<Collection> findAvailableSubscriptions(Context context, EPerson eperson) throws SQLException;
|
||||||
throws SQLException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is that e-person subscribed to that collection?
|
* Is that e-person subscribed to that collection?
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
* @param eperson find out if this e-person is subscribed
|
* @param eperson find out if this e-person is subscribed
|
||||||
* @param collection find out if subscribed to this collection
|
* @param dSpaceObject find out if subscribed to this dSpaceObject
|
||||||
* @return <code>true</code> if they are subscribed
|
* @return <code>true</code> if they are subscribed
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public boolean isSubscribed(Context context, EPerson eperson,
|
public boolean isSubscribed(Context context, EPerson eperson, DSpaceObject dSpaceObject) throws SQLException;
|
||||||
Collection collection) throws SQLException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete subscription by collection.
|
* Delete subscription by collection.
|
||||||
*
|
*
|
||||||
* @param context DSpace context
|
* @param context DSpace context
|
||||||
* @param collection find out if subscribed to this collection
|
* @param dSpaceObject find out if subscribed to this dSpaceObject
|
||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public void deleteByCollection(Context context, Collection collection) throws SQLException;
|
public void deleteByDspaceObject(Context context, DSpaceObject dSpaceObject) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete subscription by eperson (subscriber).
|
* Delete subscription by eperson (subscriber).
|
||||||
@@ -125,4 +149,92 @@ public interface SubscribeService {
|
|||||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
*/
|
*/
|
||||||
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException;
|
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException;
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Finds a subscription by id
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param id the id of subscription to be searched
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
public Subscription findById(Context context, int id) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a subscription by id
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param id Integer id
|
||||||
|
* @param subscriptionParameterList List<SubscriptionParameter> subscriptionParameterList
|
||||||
|
* @param subscriptionType type
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
public Subscription updateSubscription(Context context, Integer id, String subscriptionType,
|
||||||
|
List<SubscriptionParameter> subscriptionParameterList) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a parameter to a subscription
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param id Integer id
|
||||||
|
* @param subscriptionParameter SubscriptionParameter subscriptionParameter
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
public Subscription addSubscriptionParameter(Context context,Integer id,
|
||||||
|
SubscriptionParameter subscriptionParameter) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a parameter from subscription
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param id Integer id
|
||||||
|
* @param subscriptionParam SubscriptionParameter subscriptionParameter
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
public Subscription removeSubscriptionParameter(Context context, Integer id,
|
||||||
|
SubscriptionParameter subscriptionParam) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a subscription
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param subscription The subscription to delete
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
public void deleteSubscription(Context context, Subscription subscription) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all subscriptions by subscriptionType and frequency
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param subscriptionType Could be "content" or "statistics". NOTE: in DSpace we have only "content"
|
||||||
|
* @param frequencyValue Could be "D" stand for Day, "W" stand for Week, and "M" stand for Month
|
||||||
|
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||||
|
*/
|
||||||
|
public List<Subscription> findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
|
||||||
|
String subscriptionType, String frequencyValue) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts all subscriptions
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
*/
|
||||||
|
public Long countAll(Context context) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts all subscriptions by ePerson
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param ePerson EPerson ePerson
|
||||||
|
*/
|
||||||
|
public Long countSubscriptionsByEPerson(Context context, EPerson ePerson) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts all subscriptions by ePerson and DSO
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param ePerson EPerson ePerson
|
||||||
|
* @param dSpaceObject DSpaceObject dSpaceObject
|
||||||
|
*/
|
||||||
|
public Long countByEPersonAndDSO(Context context, EPerson ePerson, DSpaceObject dSpaceObject) throws SQLException;
|
||||||
|
|
||||||
|
}
|
@@ -21,6 +21,7 @@ import org.dspace.content.MetadataValue;
|
|||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
import org.dspace.content.logic.Filter;
|
import org.dspace.content.logic.Filter;
|
||||||
import org.dspace.content.logic.LogicalStatementException;
|
import org.dspace.content.logic.LogicalStatementException;
|
||||||
|
import org.dspace.content.logic.TrueFilter;
|
||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
@@ -28,6 +29,7 @@ import org.dspace.identifier.doi.DOIConnector;
|
|||||||
import org.dspace.identifier.doi.DOIIdentifierException;
|
import org.dspace.identifier.doi.DOIIdentifierException;
|
||||||
import org.dspace.identifier.doi.DOIIdentifierNotApplicableException;
|
import org.dspace.identifier.doi.DOIIdentifierNotApplicableException;
|
||||||
import org.dspace.identifier.service.DOIService;
|
import org.dspace.identifier.service.DOIService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -44,6 +46,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
* <p>Any identifier a method of this class returns is a string in the following format: doi:10.123/456.</p>
|
* <p>Any identifier a method of this class returns is a string in the following format: doi:10.123/456.</p>
|
||||||
*
|
*
|
||||||
* @author Pascal-Nicolas Becker
|
* @author Pascal-Nicolas Becker
|
||||||
|
* @author Kim Shepherd
|
||||||
*/
|
*/
|
||||||
public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
||||||
private static final Logger log = LoggerFactory.getLogger(DOIIdentifierProvider.class);
|
private static final Logger log = LoggerFactory.getLogger(DOIIdentifierProvider.class);
|
||||||
@@ -71,16 +74,44 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
public static final String MD_SCHEMA = "dc";
|
public static final String MD_SCHEMA = "dc";
|
||||||
public static final String DOI_ELEMENT = "identifier";
|
public static final String DOI_ELEMENT = "identifier";
|
||||||
public static final String DOI_QUALIFIER = "uri";
|
public static final String DOI_QUALIFIER = "uri";
|
||||||
|
// The DOI is queued for registered with the service provider
|
||||||
public static final Integer TO_BE_REGISTERED = 1;
|
public static final Integer TO_BE_REGISTERED = 1;
|
||||||
|
// The DOI is queued for reservation with the service provider
|
||||||
public static final Integer TO_BE_RESERVED = 2;
|
public static final Integer TO_BE_RESERVED = 2;
|
||||||
|
// The DOI has been registered online
|
||||||
public static final Integer IS_REGISTERED = 3;
|
public static final Integer IS_REGISTERED = 3;
|
||||||
|
// The DOI has been reserved online
|
||||||
public static final Integer IS_RESERVED = 4;
|
public static final Integer IS_RESERVED = 4;
|
||||||
|
// The DOI is reserved and requires an updated metadata record to be sent to the service provider
|
||||||
public static final Integer UPDATE_RESERVED = 5;
|
public static final Integer UPDATE_RESERVED = 5;
|
||||||
|
// The DOI is registered and requires an updated metadata record to be sent to the service provider
|
||||||
public static final Integer UPDATE_REGISTERED = 6;
|
public static final Integer UPDATE_REGISTERED = 6;
|
||||||
|
// The DOI metadata record should be updated before performing online registration
|
||||||
public static final Integer UPDATE_BEFORE_REGISTRATION = 7;
|
public static final Integer UPDATE_BEFORE_REGISTRATION = 7;
|
||||||
|
// The DOI will be deleted locally and marked as deleted in the DOI service provider
|
||||||
public static final Integer TO_BE_DELETED = 8;
|
public static final Integer TO_BE_DELETED = 8;
|
||||||
|
// The DOI has been deleted and is no longer associated with an item
|
||||||
public static final Integer DELETED = 9;
|
public static final Integer DELETED = 9;
|
||||||
|
// The DOI is created in the database and is waiting for either successful filter check on item install or
|
||||||
|
// manual intervention by an administrator to proceed to reservation or registration
|
||||||
|
public static final Integer PENDING = 10;
|
||||||
|
// The DOI is created in the database, but no more context is known
|
||||||
|
public static final Integer MINTED = 11;
|
||||||
|
|
||||||
|
public static final String[] statusText = {
|
||||||
|
"UNKNOWN", // 0
|
||||||
|
"TO_BE_REGISTERED", // 1
|
||||||
|
"TO_BE_RESERVED", // 2
|
||||||
|
"IS_REGISTERED", // 3
|
||||||
|
"IS_RESERVED", // 4
|
||||||
|
"UPDATE_RESERVED", // 5
|
||||||
|
"UPDATE_REGISTERED", // 6
|
||||||
|
"UPDATE_BEFORE_REGISTRATION", // 7
|
||||||
|
"TO_BE_DELETED", // 8
|
||||||
|
"DELETED", // 9
|
||||||
|
"PENDING", // 10
|
||||||
|
"MINTED", // 11
|
||||||
|
};
|
||||||
|
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected DOIService doiService;
|
protected DOIService doiService;
|
||||||
@@ -89,8 +120,6 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected ItemService itemService;
|
protected ItemService itemService;
|
||||||
|
|
||||||
protected Filter filterService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty / default constructor for Spring
|
* Empty / default constructor for Spring
|
||||||
*/
|
*/
|
||||||
@@ -153,16 +182,6 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
this.connector = connector;
|
this.connector = connector;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the Filter to use when testing items to see if a DOI should be registered
|
|
||||||
* Spring will use this setter to set the filter from the configured property in identifier-services.xml
|
|
||||||
* @param filterService - an object implementing the org.dspace.content.logic.Filter interface
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setFilterService(Filter filterService) {
|
|
||||||
this.filterService = filterService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This identifier provider supports identifiers of type
|
* This identifier provider supports identifiers of type
|
||||||
* {@link org.dspace.identifier.DOI}.
|
* {@link org.dspace.identifier.DOI}.
|
||||||
@@ -206,7 +225,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
@Override
|
@Override
|
||||||
public String register(Context context, DSpaceObject dso)
|
public String register(Context context, DSpaceObject dso)
|
||||||
throws IdentifierException {
|
throws IdentifierException {
|
||||||
return register(context, dso, false);
|
return register(context, dso, this.filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,29 +238,29 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void register(Context context, DSpaceObject dso, String identifier)
|
public void register(Context context, DSpaceObject dso, String identifier)
|
||||||
throws IdentifierException {
|
throws IdentifierException {
|
||||||
register(context, dso, identifier, false);
|
register(context, dso, identifier, this.filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new DOI for a given DSpaceObject
|
* Register a new DOI for a given DSpaceObject
|
||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by the new DOI
|
* @param dso - DSpaceObject identified by the new DOI
|
||||||
* @param skipFilter - boolean indicating whether to skip any filtering of items before performing registration
|
* @param filter - Logical item filter to determine whether this identifier should be registered
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String register(Context context, DSpaceObject dso, boolean skipFilter)
|
public String register(Context context, DSpaceObject dso, Filter filter)
|
||||||
throws IdentifierException {
|
throws IdentifierException {
|
||||||
if (!(dso instanceof Item)) {
|
if (!(dso instanceof Item)) {
|
||||||
// DOI are currently assigned only to Item
|
// DOI are currently assigned only to Item
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String doi = mint(context, dso, skipFilter);
|
String doi = mint(context, dso, filter);
|
||||||
|
|
||||||
// register tries to reserve doi if it's not already.
|
// register tries to reserve doi if it's not already.
|
||||||
// So we don't have to reserve it here.
|
// So we don't have to reserve it here.
|
||||||
register(context, dso, doi, skipFilter);
|
register(context, dso, doi, filter);
|
||||||
return doi;
|
return doi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,11 +269,11 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by the new DOI
|
* @param dso - DSpaceObject identified by the new DOI
|
||||||
* @param identifier - String containing the DOI to register
|
* @param identifier - String containing the DOI to register
|
||||||
* @param skipFilter - boolean indicating whether to skip any filtering of items before performing registration
|
* @param filter - Logical item filter to determine whether this identifier should be registered
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void register(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
|
public void register(Context context, DSpaceObject dso, String identifier, Filter filter)
|
||||||
throws IdentifierException {
|
throws IdentifierException {
|
||||||
if (!(dso instanceof Item)) {
|
if (!(dso instanceof Item)) {
|
||||||
// DOI are currently assigned only to Item
|
// DOI are currently assigned only to Item
|
||||||
@@ -265,7 +284,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
|
|
||||||
// search DOI in our db
|
// search DOI in our db
|
||||||
try {
|
try {
|
||||||
doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
|
doiRow = loadOrCreateDOI(context, dso, doi, filter);
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
log.error("Error in databse connection: " + ex.getMessage());
|
log.error("Error in databse connection: " + ex.getMessage());
|
||||||
throw new RuntimeException("Error in database conncetion.", ex);
|
throw new RuntimeException("Error in database conncetion.", ex);
|
||||||
@@ -277,7 +296,6 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
+ "is marked as DELETED.", DOIIdentifierException.DOI_IS_DELETED);
|
+ "is marked as DELETED.", DOIIdentifierException.DOI_IS_DELETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check status of DOI
|
|
||||||
if (IS_REGISTERED.equals(doiRow.getStatus())) {
|
if (IS_REGISTERED.equals(doiRow.getStatus())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -290,6 +308,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
log.warn("SQLException while changing status of DOI {} to be registered.", doi);
|
log.warn("SQLException while changing status of DOI {} to be registered.", doi);
|
||||||
throw new RuntimeException(sqle);
|
throw new RuntimeException(sqle);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -309,7 +328,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void reserve(Context context, DSpaceObject dso, String identifier)
|
public void reserve(Context context, DSpaceObject dso, String identifier)
|
||||||
throws IdentifierException, IllegalArgumentException {
|
throws IdentifierException, IllegalArgumentException {
|
||||||
reserve(context, dso, identifier, false);
|
reserve(context, dso, identifier, this.filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -317,20 +336,18 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by this DOI
|
* @param dso - DSpaceObject identified by this DOI
|
||||||
* @param identifier - String containing the DOI to reserve
|
* @param identifier - String containing the DOI to reserve
|
||||||
* @param skipFilter - boolean indicating whether to skip any filtering of items before performing reservation
|
* @param filter - Logical item filter to determine whether this identifier should be reserved
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void reserve(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
|
public void reserve(Context context, DSpaceObject dso, String identifier, Filter filter)
|
||||||
throws IdentifierException, IllegalArgumentException {
|
throws IdentifierException, IllegalArgumentException {
|
||||||
String doi = doiService.formatIdentifier(identifier);
|
String doi = doiService.formatIdentifier(identifier);
|
||||||
DOI doiRow = null;
|
DOI doiRow = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// if the doi is in our db already loadOrCreateDOI just returns.
|
doiRow = loadOrCreateDOI(context, dso, doi, filter);
|
||||||
// if it is not loadOrCreateDOI safes the doi.
|
|
||||||
doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
|
|
||||||
} catch (SQLException sqle) {
|
} catch (SQLException sqle) {
|
||||||
throw new RuntimeException(sqle);
|
throw new RuntimeException(sqle);
|
||||||
}
|
}
|
||||||
@@ -359,7 +376,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
*/
|
*/
|
||||||
public void reserveOnline(Context context, DSpaceObject dso, String identifier)
|
public void reserveOnline(Context context, DSpaceObject dso, String identifier)
|
||||||
throws IdentifierException, IllegalArgumentException, SQLException {
|
throws IdentifierException, IllegalArgumentException, SQLException {
|
||||||
reserveOnline(context, dso, identifier, false);
|
reserveOnline(context, dso, identifier, this.filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -367,16 +384,16 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by this DOI
|
* @param dso - DSpaceObject identified by this DOI
|
||||||
* @param identifier - String containing the DOI to reserve
|
* @param identifier - String containing the DOI to reserve
|
||||||
* @param skipFilter - skip the filters for {@link checkMintable(Context, DSpaceObject)}
|
* @param filter - Logical item filter to determine whether this identifier should be reserved online
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public void reserveOnline(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
|
public void reserveOnline(Context context, DSpaceObject dso, String identifier, Filter filter)
|
||||||
throws IdentifierException, IllegalArgumentException, SQLException {
|
throws IdentifierException, IllegalArgumentException, SQLException {
|
||||||
String doi = doiService.formatIdentifier(identifier);
|
String doi = doiService.formatIdentifier(identifier);
|
||||||
// get TableRow and ensure DOI belongs to dso regarding our db
|
// get TableRow and ensure DOI belongs to dso regarding our db
|
||||||
DOI doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
|
DOI doiRow = loadOrCreateDOI(context, dso, doi, filter);
|
||||||
|
|
||||||
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
|
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
|
||||||
throw new DOIIdentifierException("You tried to reserve a DOI that "
|
throw new DOIIdentifierException("You tried to reserve a DOI that "
|
||||||
@@ -402,7 +419,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
public void registerOnline(Context context, DSpaceObject dso, String identifier)
|
public void registerOnline(Context context, DSpaceObject dso, String identifier)
|
||||||
throws IdentifierException, IllegalArgumentException, SQLException {
|
throws IdentifierException, IllegalArgumentException, SQLException {
|
||||||
|
|
||||||
registerOnline(context, dso, identifier, false);
|
registerOnline(context, dso, identifier, this.filter);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,18 +428,17 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by this DOI
|
* @param dso - DSpaceObject identified by this DOI
|
||||||
* @param identifier - String containing the DOI to register
|
* @param identifier - String containing the DOI to register
|
||||||
* @param skipFilter - skip filters for {@link checkMintable(Context, DSpaceObject)}
|
* @param filter - Logical item filter to determine whether this identifier should be registered online
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public void registerOnline(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
|
public void registerOnline(Context context, DSpaceObject dso, String identifier, Filter filter)
|
||||||
throws IdentifierException, IllegalArgumentException, SQLException {
|
throws IdentifierException, IllegalArgumentException, SQLException {
|
||||||
log.debug("registerOnline: skipFilter is " + skipFilter);
|
|
||||||
|
|
||||||
String doi = doiService.formatIdentifier(identifier);
|
String doi = doiService.formatIdentifier(identifier);
|
||||||
// get TableRow and ensure DOI belongs to dso regarding our db
|
// get TableRow and ensure DOI belongs to dso regarding our db
|
||||||
DOI doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
|
DOI doiRow = loadOrCreateDOI(context, dso, doi, filter);
|
||||||
|
|
||||||
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
|
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
|
||||||
throw new DOIIdentifierException("You tried to register a DOI that "
|
throw new DOIIdentifierException("You tried to register a DOI that "
|
||||||
@@ -435,7 +451,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
} catch (DOIIdentifierException die) {
|
} catch (DOIIdentifierException die) {
|
||||||
// do we have to reserve DOI before we can register it?
|
// do we have to reserve DOI before we can register it?
|
||||||
if (die.getCode() == DOIIdentifierException.RESERVE_FIRST) {
|
if (die.getCode() == DOIIdentifierException.RESERVE_FIRST) {
|
||||||
this.reserveOnline(context, dso, identifier, skipFilter);
|
this.reserveOnline(context, dso, identifier, filter);
|
||||||
connector.registerDOI(context, dso, doi);
|
connector.registerDOI(context, dso, doi);
|
||||||
} else {
|
} else {
|
||||||
throw die;
|
throw die;
|
||||||
@@ -471,17 +487,23 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
throws IdentifierException, IllegalArgumentException, SQLException {
|
throws IdentifierException, IllegalArgumentException, SQLException {
|
||||||
|
|
||||||
String doi = doiService.formatIdentifier(identifier);
|
String doi = doiService.formatIdentifier(identifier);
|
||||||
|
// Use the default filter unless we find the object
|
||||||
boolean skipFilter = false;
|
Filter updateFilter = this.filter;
|
||||||
|
|
||||||
if (doiService.findDOIByDSpaceObject(context, dso) != null) {
|
if (doiService.findDOIByDSpaceObject(context, dso) != null) {
|
||||||
// We can skip the filter here since we know the DOI already exists for the item
|
// We can skip the filter here since we know the DOI already exists for the item
|
||||||
log.debug("updateMetadata: found DOIByDSpaceObject: " +
|
log.debug("updateMetadata: found DOIByDSpaceObject: " +
|
||||||
doiService.findDOIByDSpaceObject(context, dso).getDoi());
|
doiService.findDOIByDSpaceObject(context, dso).getDoi());
|
||||||
skipFilter = true;
|
updateFilter = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
|
||||||
|
"always_true_filter", TrueFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
DOI doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
|
DOI doiRow = loadOrCreateDOI(context, dso, doi, updateFilter);
|
||||||
|
|
||||||
|
if (PENDING.equals(doiRow.getStatus()) || MINTED.equals(doiRow.getStatus())) {
|
||||||
|
log.info("Not updating metadata for PENDING or MINTED doi: " + doi);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
|
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
|
||||||
throw new DOIIdentifierException("You tried to register a DOI that "
|
throw new DOIIdentifierException("You tried to register a DOI that "
|
||||||
@@ -571,19 +593,19 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
@Override
|
@Override
|
||||||
public String mint(Context context, DSpaceObject dso)
|
public String mint(Context context, DSpaceObject dso)
|
||||||
throws IdentifierException {
|
throws IdentifierException {
|
||||||
return mint(context, dso, false);
|
return mint(context, dso, this.filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mint a new DOI in DSpace - this is usually the first step of registration
|
* Mint a new DOI in DSpace - this is usually the first step of registration
|
||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by the new identifier
|
* @param dso - DSpaceObject identified by the new identifier
|
||||||
* @param skipFilter - boolean indicating whether to skip any filtering of items before minting.
|
* @param filter - Logical item filter to determine whether this identifier should be registered
|
||||||
* @return a String containing the new identifier
|
* @return a String containing the new identifier
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String mint(Context context, DSpaceObject dso, boolean skipFilter) throws IdentifierException {
|
public String mint(Context context, DSpaceObject dso, Filter filter) throws IdentifierException {
|
||||||
|
|
||||||
String doi = null;
|
String doi = null;
|
||||||
try {
|
try {
|
||||||
@@ -597,7 +619,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
}
|
}
|
||||||
if (null == doi) {
|
if (null == doi) {
|
||||||
try {
|
try {
|
||||||
DOI doiRow = loadOrCreateDOI(context, dso, null, skipFilter);
|
DOI doiRow = loadOrCreateDOI(context, dso, null, filter);
|
||||||
doi = DOI.SCHEME + doiRow.getDoi();
|
doi = DOI.SCHEME + doiRow.getDoi();
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
@@ -895,7 +917,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
*/
|
*/
|
||||||
protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdentifier)
|
protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdentifier)
|
||||||
throws SQLException, DOIIdentifierException, IdentifierNotApplicableException {
|
throws SQLException, DOIIdentifierException, IdentifierNotApplicableException {
|
||||||
return loadOrCreateDOI(context, dso, doiIdentifier, false);
|
return loadOrCreateDOI(context, dso, doiIdentifier, this.filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -910,13 +932,13 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject to identify
|
* @param dso - DSpaceObject to identify
|
||||||
* @param doiIdentifier - DOI to load or create (null to mint a new one)
|
* @param doiIdentifier - DOI to load or create (null to mint a new one)
|
||||||
* @param skipFilter - Whether or not to skip the filters for the checkMintable() check
|
* @param filter - Logical item filter to determine whether this identifier should be registered
|
||||||
* @return
|
* @return
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
* @throws DOIIdentifierException
|
* @throws DOIIdentifierException
|
||||||
* @throws org.dspace.identifier.IdentifierNotApplicableException passed through.
|
* @throws org.dspace.identifier.IdentifierNotApplicableException passed through.
|
||||||
*/
|
*/
|
||||||
protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdentifier, boolean skipFilter)
|
protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdentifier, Filter filter)
|
||||||
throws SQLException, DOIIdentifierException, IdentifierNotApplicableException {
|
throws SQLException, DOIIdentifierException, IdentifierNotApplicableException {
|
||||||
|
|
||||||
DOI doi = null;
|
DOI doi = null;
|
||||||
@@ -954,6 +976,8 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
// doi is assigned to a DSO; is it assigned to our specific dso?
|
// doi is assigned to a DSO; is it assigned to our specific dso?
|
||||||
// check if DOI already belongs to dso
|
// check if DOI already belongs to dso
|
||||||
if (dso.getID().equals(doi.getDSpaceObject().getID())) {
|
if (dso.getID().equals(doi.getDSpaceObject().getID())) {
|
||||||
|
// Before we return this, check the filter
|
||||||
|
checkMintable(context, filter, dso);
|
||||||
return doi;
|
return doi;
|
||||||
} else {
|
} else {
|
||||||
throw new DOIIdentifierException("Trying to create a DOI " +
|
throw new DOIIdentifierException("Trying to create a DOI " +
|
||||||
@@ -963,15 +987,8 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we did not find the doi in the database or shall reassign it. Before doing so, we should check if a
|
// Check if this item is eligible for minting. An IdentifierNotApplicableException will be thrown if not.
|
||||||
// filter is in place to prevent the creation of new DOIs for certain items.
|
checkMintable(context, filter, dso);
|
||||||
if (skipFilter) {
|
|
||||||
log.warn("loadOrCreateDOI: Skipping default item filter");
|
|
||||||
} else {
|
|
||||||
// Find out if we're allowed to create a DOI
|
|
||||||
// throws an exception if creation of a new DOI is prohibited by a filter
|
|
||||||
checkMintable(context, dso);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check prefix
|
// check prefix
|
||||||
if (!doiIdentifier.startsWith(this.getPrefix() + "/")) {
|
if (!doiIdentifier.startsWith(this.getPrefix() + "/")) {
|
||||||
@@ -984,15 +1001,8 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
doi = doiService.create(context);
|
doi = doiService.create(context);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We need to generate a new DOI. Before doing so, we should check if a
|
// Check if this item is eligible for minting. An IdentifierNotApplicableException will be thrown if not.
|
||||||
// filter is in place to prevent the creation of new DOIs for certain items.
|
checkMintable(context, filter, dso);
|
||||||
if (skipFilter) {
|
|
||||||
log.warn("loadOrCreateDOI: Skipping default item filter");
|
|
||||||
} else {
|
|
||||||
// Find out if we're allowed to create a DOI
|
|
||||||
// throws an exception if creation of a new DOI is prohibited by a filter
|
|
||||||
checkMintable(context, dso);
|
|
||||||
}
|
|
||||||
|
|
||||||
doi = doiService.create(context);
|
doi = doiService.create(context);
|
||||||
doiIdentifier = this.getPrefix() + "/" + this.getNamespaceSeparator() +
|
doiIdentifier = this.getPrefix() + "/" + this.getNamespaceSeparator() +
|
||||||
@@ -1002,7 +1012,7 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
// prepare new doiRow
|
// prepare new doiRow
|
||||||
doi.setDoi(doiIdentifier);
|
doi.setDoi(doiIdentifier);
|
||||||
doi.setDSpaceObject(dso);
|
doi.setDSpaceObject(dso);
|
||||||
doi.setStatus(null);
|
doi.setStatus(MINTED);
|
||||||
try {
|
try {
|
||||||
doiService.update(context, doi);
|
doiService.update(context, doi);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
@@ -1102,20 +1112,32 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
/**
|
/**
|
||||||
* Checks to see if an item can have a DOI minted, using the configured logical filter
|
* Checks to see if an item can have a DOI minted, using the configured logical filter
|
||||||
* @param context
|
* @param context
|
||||||
|
* @param filter Logical item filter to apply
|
||||||
* @param dso The item to be evaluated
|
* @param dso The item to be evaluated
|
||||||
* @throws DOIIdentifierNotApplicableException
|
* @throws DOIIdentifierNotApplicableException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void checkMintable(Context context, DSpaceObject dso) throws DOIIdentifierNotApplicableException {
|
public void checkMintable(Context context, Filter filter, DSpaceObject dso)
|
||||||
|
throws DOIIdentifierNotApplicableException {
|
||||||
|
if (filter == null) {
|
||||||
|
Filter trueFilter = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
|
||||||
|
"always_true_filter", TrueFilter.class);
|
||||||
|
// If a null filter was passed, and we have a good default filter to apply, apply it.
|
||||||
|
// Otherwise, set to TrueFilter which means "no filtering"
|
||||||
|
if (this.filter != null) {
|
||||||
|
filter = this.filter;
|
||||||
|
} else {
|
||||||
|
filter = trueFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
// If the check fails, an exception will be thrown to be caught by the calling method
|
// If the check fails, an exception will be thrown to be caught by the calling method
|
||||||
if (this.filterService != null && contentServiceFactory
|
if (contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso).equals("ITEM")) {
|
||||||
.getDSpaceObjectService(dso).getTypeText(dso).equals("ITEM")) {
|
|
||||||
try {
|
try {
|
||||||
boolean result = filterService.getResult(context, (Item) dso);
|
boolean result = filter.getResult(context, (Item) dso);
|
||||||
log.debug("Result of filter for " + dso.getHandle() + " is " + result);
|
log.debug("Result of filter for " + dso.getHandle() + " is " + result);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new DOIIdentifierNotApplicableException("Item " + dso.getHandle() +
|
throw new DOIIdentifierNotApplicableException("Item " + dso.getHandle() +
|
||||||
" was evaluated as 'false' by the item filter, not minting");
|
" was evaluated as 'false' by the item filter, not minting");
|
||||||
}
|
}
|
||||||
} catch (LogicalStatementException e) {
|
} catch (LogicalStatementException e) {
|
||||||
log.error("Error evaluating item with logical filter: " + e.getLocalizedMessage());
|
log.error("Error evaluating item with logical filter: " + e.getLocalizedMessage());
|
||||||
@@ -1125,4 +1147,16 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
|
|||||||
log.debug("DOI Identifier Provider: filterService is null (ie. don't prevent DOI minting)");
|
log.debug("DOI Identifier Provider: filterService is null (ie. don't prevent DOI minting)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if an item can have a DOI minted, using the configured logical filter
|
||||||
|
* @param context
|
||||||
|
* @param dso The item to be evaluated
|
||||||
|
* @throws DOIIdentifierNotApplicableException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void checkMintable(Context context, DSpaceObject dso) throws DOIIdentifierNotApplicableException {
|
||||||
|
checkMintable(context, this.filter, dso);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -12,8 +12,9 @@ import java.sql.SQLException;
|
|||||||
|
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.content.logic.Filter;
|
import org.dspace.content.logic.Filter;
|
||||||
|
import org.dspace.content.logic.TrueFilter;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This abstract class adds extra method signatures so that implementing IdentifierProviders can
|
* This abstract class adds extra method signatures so that implementing IdentifierProviders can
|
||||||
@@ -24,26 +25,28 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
*/
|
*/
|
||||||
public abstract class FilteredIdentifierProvider extends IdentifierProvider {
|
public abstract class FilteredIdentifierProvider extends IdentifierProvider {
|
||||||
|
|
||||||
protected Filter filterService;
|
protected Filter filter = DSpaceServicesFactory.getInstance()
|
||||||
|
.getServiceManager().getServiceByName("always_true_filter", TrueFilter.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for spring to set the filter service from the property in configuration XML
|
* Setter for spring to set the default filter from the property in configuration XML
|
||||||
* @param filterService - an object implementing the org.dspace.content.logic.Filter interface
|
* @param filter - an object implementing the org.dspace.content.logic.Filter interface
|
||||||
*/
|
*/
|
||||||
@Autowired
|
public void setFilter(Filter filter) {
|
||||||
public void setFilterService(Filter filterService) {
|
if (filter != null) {
|
||||||
this.filterService = filterService;
|
this.filter = filter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new identifier for a given DSpaceObject
|
* Register a new identifier for a given DSpaceObject
|
||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject to use for identifier registration
|
* @param dso - DSpaceObject to use for identifier registration
|
||||||
* @param skipFilter - boolean indicating whether to skip any filtering of items before performing registration
|
* @param filter - Logical item filter to determine whether this identifier should be registered
|
||||||
* @return identifier
|
* @return identifier
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
*/
|
*/
|
||||||
public abstract String register(Context context, DSpaceObject dso, boolean skipFilter)
|
public abstract String register(Context context, DSpaceObject dso, Filter filter)
|
||||||
throws IdentifierException;
|
throws IdentifierException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,10 +54,10 @@ public abstract class FilteredIdentifierProvider extends IdentifierProvider {
|
|||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by the new identifier
|
* @param dso - DSpaceObject identified by the new identifier
|
||||||
* @param identifier - String containing the identifier to register
|
* @param identifier - String containing the identifier to register
|
||||||
* @param skipFilter - boolean indicating whether to skip any filtering of items before performing registration
|
* @param filter - Logical item filter to determine whether this identifier should be registered
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
*/
|
*/
|
||||||
public abstract void register(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
|
public abstract void register(Context context, DSpaceObject dso, String identifier, Filter filter)
|
||||||
throws IdentifierException;
|
throws IdentifierException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,23 +65,23 @@ public abstract class FilteredIdentifierProvider extends IdentifierProvider {
|
|||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by this identifier
|
* @param dso - DSpaceObject identified by this identifier
|
||||||
* @param identifier - String containing the identifier to reserve
|
* @param identifier - String containing the identifier to reserve
|
||||||
* @param skipFilter - boolean indicating whether to skip any filtering of items before performing reservation
|
* @param filter - Logical item filter to determine whether this identifier should be reserved
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
*/
|
*/
|
||||||
public abstract void reserve(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
|
public abstract void reserve(Context context, DSpaceObject dso, String identifier, Filter filter)
|
||||||
throws IdentifierException, IllegalArgumentException, SQLException;
|
throws IdentifierException, IllegalArgumentException, SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mint a new identifier in DSpace - this is usually the first step of registration
|
* Mint a new identifier in DSpace - this is usually the first step of registration
|
||||||
* @param context - DSpace context
|
* @param context - DSpace context
|
||||||
* @param dso - DSpaceObject identified by the new identifier
|
* @param dso - DSpaceObject identified by the new identifier
|
||||||
* @param skipFilter - boolean indicating whether to skip any filtering of items before minting.
|
* @param filter - Logical item filter to determine whether this identifier should be registered
|
||||||
* @return a String containing the new identifier
|
* @return a String containing the new identifier
|
||||||
* @throws IdentifierException
|
* @throws IdentifierException
|
||||||
*/
|
*/
|
||||||
public abstract String mint(Context context, DSpaceObject dso, boolean skipFilter) throws IdentifierException;
|
public abstract String mint(Context context, DSpaceObject dso, Filter filter) throws IdentifierException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check configured item filters to see if this identifier is allowed to be minted
|
* Check configured item filters to see if this identifier is allowed to be minted
|
||||||
@@ -88,5 +91,13 @@ public abstract class FilteredIdentifierProvider extends IdentifierProvider {
|
|||||||
*/
|
*/
|
||||||
public abstract void checkMintable(Context context, DSpaceObject dso) throws IdentifierException;
|
public abstract void checkMintable(Context context, DSpaceObject dso) throws IdentifierException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check configured item filters to see if this identifier is allowed to be minted
|
||||||
|
* @param context - DSpace context
|
||||||
|
* @param filter - Logical item filter
|
||||||
|
* @param dso - DSpaceObject to be inspected
|
||||||
|
* @throws IdentifierException
|
||||||
|
*/
|
||||||
|
public abstract void checkMintable(Context context, Filter filter, DSpaceObject dso) throws IdentifierException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@ package org.dspace.identifier;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@@ -17,6 +18,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.logic.Filter;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.handle.service.HandleService;
|
import org.dspace.handle.service.HandleService;
|
||||||
import org.dspace.identifier.service.IdentifierService;
|
import org.dspace.identifier.service.IdentifierService;
|
||||||
@@ -44,7 +46,6 @@ public class IdentifierServiceImpl implements IdentifierService {
|
|||||||
protected HandleService handleService;
|
protected HandleService handleService;
|
||||||
|
|
||||||
protected IdentifierServiceImpl() {
|
protected IdentifierServiceImpl() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
@@ -98,7 +99,7 @@ public class IdentifierServiceImpl implements IdentifierService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(Context context, DSpaceObject dso)
|
public void register(Context context, DSpaceObject dso)
|
||||||
throws AuthorizeException, SQLException, IdentifierException {
|
throws AuthorizeException, SQLException, IdentifierException {
|
||||||
//We need to commit our context because one of the providers might require the handle created above
|
//We need to commit our context because one of the providers might require the handle created above
|
||||||
// Next resolve all other services
|
// Next resolve all other services
|
||||||
for (IdentifierProvider service : providers) {
|
for (IdentifierProvider service : providers) {
|
||||||
@@ -112,11 +113,99 @@ public class IdentifierServiceImpl implements IdentifierService {
|
|||||||
contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
|
contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(Context context, DSpaceObject dso, Class<? extends Identifier> type, Filter filter)
|
||||||
|
throws AuthorizeException, SQLException, IdentifierException {
|
||||||
|
boolean registered = false;
|
||||||
|
// Iterate all services and register identifiers as appropriate
|
||||||
|
for (IdentifierProvider service : providers) {
|
||||||
|
if (service.supports(type)) {
|
||||||
|
try {
|
||||||
|
if (service instanceof FilteredIdentifierProvider) {
|
||||||
|
FilteredIdentifierProvider filteredService = (FilteredIdentifierProvider)service;
|
||||||
|
filteredService.register(context, dso, filter);
|
||||||
|
} else {
|
||||||
|
service.register(context, dso);
|
||||||
|
}
|
||||||
|
registered = true;
|
||||||
|
} catch (IdentifierNotApplicableException e) {
|
||||||
|
log.warn("Identifier not registered (inapplicable): " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!registered) {
|
||||||
|
throw new IdentifierException("Cannot register identifier: Didn't "
|
||||||
|
+ "find a provider that supports this identifier.");
|
||||||
|
}
|
||||||
|
// Update our item / collection / community
|
||||||
|
contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(Context context, DSpaceObject dso, Class<? extends Identifier> type)
|
||||||
|
throws AuthorizeException, SQLException, IdentifierException {
|
||||||
|
boolean registered = false;
|
||||||
|
// Iterate all services and register identifiers as appropriate
|
||||||
|
for (IdentifierProvider service : providers) {
|
||||||
|
if (service.supports(type)) {
|
||||||
|
try {
|
||||||
|
service.register(context, dso);
|
||||||
|
registered = true;
|
||||||
|
} catch (IdentifierNotApplicableException e) {
|
||||||
|
log.warn("Identifier not registered (inapplicable): " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!registered) {
|
||||||
|
throw new IdentifierException("Cannot register identifier: Didn't "
|
||||||
|
+ "find a provider that supports this identifier.");
|
||||||
|
}
|
||||||
|
// Update our item / collection / community
|
||||||
|
contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(Context context, DSpaceObject dso, Map<Class<? extends Identifier>, Filter> typeFilters)
|
||||||
|
throws AuthorizeException, SQLException, IdentifierException {
|
||||||
|
// Iterate all services and register identifiers as appropriate
|
||||||
|
for (IdentifierProvider service : providers) {
|
||||||
|
try {
|
||||||
|
// If the service supports filtering, look through the map and the first supported class
|
||||||
|
// we find, set the filter and break. If no filter was seen for this type, just let the provider
|
||||||
|
// use its own implementation.
|
||||||
|
if (service instanceof FilteredIdentifierProvider) {
|
||||||
|
FilteredIdentifierProvider filteredService = (FilteredIdentifierProvider)service;
|
||||||
|
Filter filter = null;
|
||||||
|
for (Class<? extends Identifier> type : typeFilters.keySet()) {
|
||||||
|
if (filteredService.supports(type)) {
|
||||||
|
filter = typeFilters.get(type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filter != null) {
|
||||||
|
// Pass the found filter to the provider
|
||||||
|
filteredService.register(context, dso, filter);
|
||||||
|
} else {
|
||||||
|
// Let the provider use the default filter / behaviour
|
||||||
|
filteredService.register(context, dso);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
service.register(context, dso);
|
||||||
|
}
|
||||||
|
} catch (IdentifierNotApplicableException e) {
|
||||||
|
log.warn("Identifier not registered (inapplicable): " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update our item / collection / community
|
||||||
|
contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(Context context, DSpaceObject object, String identifier)
|
public void register(Context context, DSpaceObject object, String identifier)
|
||||||
throws AuthorizeException, SQLException, IdentifierException {
|
throws AuthorizeException, SQLException, IdentifierException {
|
||||||
//We need to commit our context because one of the providers might require the handle created above
|
// Iterate all services and register identifiers as appropriate
|
||||||
// Next resolve all other services
|
|
||||||
boolean registered = false;
|
boolean registered = false;
|
||||||
for (IdentifierProvider service : providers) {
|
for (IdentifierProvider service : providers) {
|
||||||
if (service.supports(identifier)) {
|
if (service.supports(identifier)) {
|
||||||
@@ -132,7 +221,7 @@ public class IdentifierServiceImpl implements IdentifierService {
|
|||||||
throw new IdentifierException("Cannot register identifier: Didn't "
|
throw new IdentifierException("Cannot register identifier: Didn't "
|
||||||
+ "find a provider that supports this identifier.");
|
+ "find a provider that supports this identifier.");
|
||||||
}
|
}
|
||||||
//Update our item / collection / community
|
// pdate our item / collection / community
|
||||||
contentServiceFactory.getDSpaceObjectService(object).update(context, object);
|
contentServiceFactory.getDSpaceObjectService(object).update(context, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@ import org.dspace.authorize.AuthorizeException;
|
|||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.content.MetadataValue;
|
import org.dspace.content.MetadataValue;
|
||||||
|
import org.dspace.content.logic.Filter;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.identifier.doi.DOIConnector;
|
import org.dspace.identifier.doi.DOIConnector;
|
||||||
import org.dspace.identifier.doi.DOIIdentifierException;
|
import org.dspace.identifier.doi.DOIIdentifierException;
|
||||||
@@ -49,7 +50,12 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
|
|||||||
protected VersionHistoryService versionHistoryService;
|
protected VersionHistoryService versionHistoryService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String mint(Context context, DSpaceObject dso)
|
public String mint(Context context, DSpaceObject dso) throws IdentifierException {
|
||||||
|
return mint(context, dso, this.filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String mint(Context context, DSpaceObject dso, Filter filter)
|
||||||
throws IdentifierException {
|
throws IdentifierException {
|
||||||
if (!(dso instanceof Item)) {
|
if (!(dso instanceof Item)) {
|
||||||
throw new IdentifierException("Currently only Items are supported for DOIs.");
|
throw new IdentifierException("Currently only Items are supported for DOIs.");
|
||||||
@@ -79,6 +85,9 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
|
|||||||
+ " with ID " + dso.getID() + ".", ex);
|
+ " with ID " + dso.getID() + ".", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make a call to the filter here to throw an exception instead of carrying on with removal + creation
|
||||||
|
checkMintable(context, filter, dso);
|
||||||
|
|
||||||
// check whether we have a DOI in the metadata and if we have to remove it
|
// check whether we have a DOI in the metadata and if we have to remove it
|
||||||
String metadataDOI = getDOIOutOfObject(dso);
|
String metadataDOI = getDOIOutOfObject(dso);
|
||||||
if (metadataDOI != null) {
|
if (metadataDOI != null) {
|
||||||
@@ -111,7 +120,7 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
|
|||||||
// ensure DOI exists in our database as well and return.
|
// ensure DOI exists in our database as well and return.
|
||||||
// this also checks that the doi is not assigned to another dso already.
|
// this also checks that the doi is not assigned to another dso already.
|
||||||
try {
|
try {
|
||||||
loadOrCreateDOI(context, dso, versionedDOI);
|
loadOrCreateDOI(context, dso, versionedDOI, filter);
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
log.error(
|
log.error(
|
||||||
"A problem with the database connection occurd while processing DOI " + versionedDOI + ".", ex);
|
"A problem with the database connection occurd while processing DOI " + versionedDOI + ".", ex);
|
||||||
@@ -127,7 +136,7 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
|
|||||||
// if we have a history, we have a item
|
// if we have a history, we have a item
|
||||||
doi = makeIdentifierBasedOnHistory(context, dso, history);
|
doi = makeIdentifierBasedOnHistory(context, dso, history);
|
||||||
} else {
|
} else {
|
||||||
doi = loadOrCreateDOI(context, dso, null).getDoi();
|
doi = loadOrCreateDOI(context, dso, null, filter).getDoi();
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
log.error("SQLException while creating a new DOI: ", ex);
|
log.error("SQLException while creating a new DOI: ", ex);
|
||||||
@@ -140,7 +149,12 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(Context context, DSpaceObject dso, String identifier)
|
public void register(Context context, DSpaceObject dso, String identifier) throws IdentifierException {
|
||||||
|
register(context, dso, identifier, this.filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(Context context, DSpaceObject dso, String identifier, Filter filter)
|
||||||
throws IdentifierException {
|
throws IdentifierException {
|
||||||
if (!(dso instanceof Item)) {
|
if (!(dso instanceof Item)) {
|
||||||
throw new IdentifierException("Currently only Items are supported for DOIs.");
|
throw new IdentifierException("Currently only Items are supported for DOIs.");
|
||||||
@@ -220,8 +234,14 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
|
|||||||
return doiPostfix;
|
return doiPostfix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should never return null!
|
|
||||||
protected String makeIdentifierBasedOnHistory(Context context, DSpaceObject dso, VersionHistory history)
|
protected String makeIdentifierBasedOnHistory(Context context, DSpaceObject dso, VersionHistory history)
|
||||||
|
throws AuthorizeException, SQLException, DOIIdentifierException, IdentifierNotApplicableException {
|
||||||
|
return makeIdentifierBasedOnHistory(context, dso, history, this.filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should never return null!
|
||||||
|
protected String makeIdentifierBasedOnHistory(Context context, DSpaceObject dso, VersionHistory history,
|
||||||
|
Filter filter)
|
||||||
throws AuthorizeException, SQLException, DOIIdentifierException, IdentifierNotApplicableException {
|
throws AuthorizeException, SQLException, DOIIdentifierException, IdentifierNotApplicableException {
|
||||||
// Mint foreach new version an identifier like: 12345/100.versionNumber
|
// Mint foreach new version an identifier like: 12345/100.versionNumber
|
||||||
// use the bare handle (g.e. 12345/100) for the first version.
|
// use the bare handle (g.e. 12345/100) for the first version.
|
||||||
@@ -244,6 +264,9 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (previousVersionDOI == null) {
|
if (previousVersionDOI == null) {
|
||||||
|
// Before continuing with any new DOI creation, apply the filter
|
||||||
|
checkMintable(context, filter, dso);
|
||||||
|
|
||||||
// We need to generate a new DOI.
|
// We need to generate a new DOI.
|
||||||
DOI doi = doiService.create(context);
|
DOI doi = doiService.create(context);
|
||||||
|
|
||||||
@@ -269,7 +292,7 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
|
|||||||
String.valueOf(versionHistoryService.getVersion(context, history, item).getVersionNumber()));
|
String.valueOf(versionHistoryService.getVersion(context, history, item).getVersionNumber()));
|
||||||
}
|
}
|
||||||
|
|
||||||
loadOrCreateDOI(context, dso, identifier);
|
loadOrCreateDOI(context, dso, identifier, filter);
|
||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,22 +7,32 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.identifier.doi;
|
package org.dspace.identifier.doi;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.logic.Filter;
|
||||||
|
import org.dspace.content.logic.FilterUtils;
|
||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.event.Consumer;
|
import org.dspace.event.Consumer;
|
||||||
import org.dspace.event.Event;
|
import org.dspace.event.Event;
|
||||||
|
import org.dspace.identifier.DOI;
|
||||||
import org.dspace.identifier.DOIIdentifierProvider;
|
import org.dspace.identifier.DOIIdentifierProvider;
|
||||||
import org.dspace.identifier.IdentifierException;
|
import org.dspace.identifier.IdentifierException;
|
||||||
import org.dspace.identifier.IdentifierNotFoundException;
|
import org.dspace.identifier.IdentifierNotApplicableException;
|
||||||
|
import org.dspace.identifier.factory.IdentifierServiceFactory;
|
||||||
|
import org.dspace.identifier.service.DOIService;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
import org.dspace.utils.DSpace;
|
import org.dspace.utils.DSpace;
|
||||||
import org.dspace.workflow.factory.WorkflowServiceFactory;
|
import org.dspace.workflow.factory.WorkflowServiceFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pascal-Nicolas Becker (p dot becker at tu hyphen berlin dot de)
|
* @author Pascal-Nicolas Becker (p dot becker at tu hyphen berlin dot de)
|
||||||
|
* @author Kim Shepherd
|
||||||
*/
|
*/
|
||||||
public class DOIConsumer implements Consumer {
|
public class DOIConsumer implements Consumer {
|
||||||
/**
|
/**
|
||||||
@@ -30,12 +40,15 @@ public class DOIConsumer implements Consumer {
|
|||||||
*/
|
*/
|
||||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(DOIConsumer.class);
|
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(DOIConsumer.class);
|
||||||
|
|
||||||
|
ConfigurationService configurationService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() throws Exception {
|
public void initialize() throws Exception {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
// we can ask spring to give as a properly setuped instance of
|
// we can ask spring to give as a properly setuped instance of
|
||||||
// DOIIdentifierProvider. Doing so we don't have to configure it and
|
// DOIIdentifierProvider. Doing so we don't have to configure it and
|
||||||
// can load it in consume method as this is not very expensive.
|
// can load it in consume method as this is not very expensive.
|
||||||
|
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,36 +75,73 @@ public class DOIConsumer implements Consumer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Item item = (Item) dso;
|
Item item = (Item) dso;
|
||||||
|
DOIIdentifierProvider provider = new DSpace().getSingletonService(DOIIdentifierProvider.class);
|
||||||
if (ContentServiceFactory.getInstance().getWorkspaceItemService().findByItem(ctx, item) != null
|
boolean inProgress = (ContentServiceFactory.getInstance().getWorkspaceItemService().findByItem(ctx, item)
|
||||||
|| WorkflowServiceFactory.getInstance().getWorkflowItemService().findByItem(ctx, item) != null) {
|
!= null || WorkflowServiceFactory.getInstance().getWorkflowItemService().findByItem(ctx, item) != null);
|
||||||
// ignore workflow and workspace items, DOI will be minted when item is installed
|
boolean identifiersInSubmission = configurationService.getBooleanProperty("identifiers.submission.register",
|
||||||
return;
|
false);
|
||||||
|
DOIService doiService = IdentifierServiceFactory.getInstance().getDOIService();
|
||||||
|
Filter workspaceFilter = null;
|
||||||
|
if (identifiersInSubmission) {
|
||||||
|
workspaceFilter = FilterUtils.getFilterFromConfiguration("identifiers.submission.filter.workspace");
|
||||||
}
|
}
|
||||||
|
|
||||||
DOIIdentifierProvider provider = new DSpace().getSingletonService(
|
if (inProgress && !identifiersInSubmission) {
|
||||||
DOIIdentifierProvider.class);
|
// ignore workflow and workspace items, DOI will be minted and updated when item is installed
|
||||||
|
// UNLESS special pending filter is set
|
||||||
String doi = null;
|
return;
|
||||||
|
}
|
||||||
|
DOI doi = null;
|
||||||
try {
|
try {
|
||||||
doi = provider.lookup(ctx, dso);
|
doi = doiService.findDOIByDSpaceObject(ctx, dso);
|
||||||
} catch (IdentifierNotFoundException ex) {
|
} catch (SQLException ex) {
|
||||||
// nothing to do here, next if clause will stop us from processing
|
// nothing to do here, next if clause will stop us from processing
|
||||||
// items without dois.
|
// items without dois.
|
||||||
}
|
}
|
||||||
if (doi == null) {
|
if (doi == null) {
|
||||||
log.debug("DOIConsumer cannot handles items without DOIs, skipping: "
|
// No DOI. The only time something should be minted is if we have enabled submission reg'n and
|
||||||
+ event.toString());
|
// it passes the workspace filter. We also need to update status to PENDING straight after.
|
||||||
return;
|
if (inProgress) {
|
||||||
}
|
provider.mint(ctx, dso, workspaceFilter);
|
||||||
try {
|
DOI newDoi = doiService.findDOIByDSpaceObject(ctx, dso);
|
||||||
provider.updateMetadata(ctx, dso, doi);
|
if (newDoi != null) {
|
||||||
} catch (IllegalArgumentException ex) {
|
newDoi.setStatus(DOIIdentifierProvider.PENDING);
|
||||||
// should not happen, as we got the DOI from the DOIProvider
|
doiService.update(ctx, newDoi);
|
||||||
log.warn("DOIConsumer caught an IdentifierException.", ex);
|
}
|
||||||
} catch (IdentifierException ex) {
|
} else {
|
||||||
log.warn("DOIConsumer cannot update metadata for Item with ID "
|
log.debug("DOIConsumer cannot handles items without DOIs, skipping: " + event.toString());
|
||||||
+ item.getID() + " and DOI " + doi + ".", ex);
|
}
|
||||||
|
} else {
|
||||||
|
// If in progress, we can also switch PENDING and MINTED status depending on the latest filter
|
||||||
|
// evaluation
|
||||||
|
if (inProgress) {
|
||||||
|
try {
|
||||||
|
// Check the filter
|
||||||
|
provider.checkMintable(ctx, workspaceFilter, dso);
|
||||||
|
// If we made it here, the existing doi should be back to PENDING
|
||||||
|
if (DOIIdentifierProvider.MINTED.equals(doi.getStatus())) {
|
||||||
|
doi.setStatus(DOIIdentifierProvider.PENDING);
|
||||||
|
}
|
||||||
|
} catch (IdentifierNotApplicableException e) {
|
||||||
|
// Set status to MINTED if configured to downgrade existing DOIs
|
||||||
|
if (configurationService
|
||||||
|
.getBooleanProperty("identifiers.submission.strip_pending_during_submission", true)) {
|
||||||
|
doi.setStatus(DOIIdentifierProvider.MINTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doiService.update(ctx, doi);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
provider.updateMetadata(ctx, dso, doi.getDoi());
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
// should not happen, as we got the DOI from the DOIProvider
|
||||||
|
log.warn("DOIConsumer caught an IdentifierException.", ex);
|
||||||
|
} catch (IdentifierException ex) {
|
||||||
|
log.warn("DOIConsumer cannot update metadata for Item with ID "
|
||||||
|
+ item.getID() + " and DOI " + doi + ".", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,6 +30,9 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.logic.Filter;
|
||||||
|
import org.dspace.content.logic.FilterUtils;
|
||||||
|
import org.dspace.content.logic.TrueFilter;
|
||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
@@ -61,7 +64,8 @@ public class DOIOrganiser {
|
|||||||
protected ItemService itemService;
|
protected ItemService itemService;
|
||||||
protected DOIService doiService;
|
protected DOIService doiService;
|
||||||
protected ConfigurationService configurationService;
|
protected ConfigurationService configurationService;
|
||||||
protected boolean skipFilter;
|
// This filter will override the default provider filter / behaviour
|
||||||
|
protected Filter filter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor to be called within the main() method
|
* Constructor to be called within the main() method
|
||||||
@@ -76,7 +80,8 @@ public class DOIOrganiser {
|
|||||||
this.itemService = ContentServiceFactory.getInstance().getItemService();
|
this.itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
this.doiService = IdentifierServiceFactory.getInstance().getDOIService();
|
this.doiService = IdentifierServiceFactory.getInstance().getDOIService();
|
||||||
this.configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
this.configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
this.skipFilter = false;
|
this.filter = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
|
||||||
|
"always_true_filter", TrueFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,12 +126,13 @@ public class DOIOrganiser {
|
|||||||
"Perform online metadata update for all identifiers queued for metadata update.");
|
"Perform online metadata update for all identifiers queued for metadata update.");
|
||||||
options.addOption("d", "delete-all", false,
|
options.addOption("d", "delete-all", false,
|
||||||
"Perform online deletion for all identifiers queued for deletion.");
|
"Perform online deletion for all identifiers queued for deletion.");
|
||||||
|
|
||||||
options.addOption("q", "quiet", false,
|
options.addOption("q", "quiet", false,
|
||||||
"Turn the command line output off.");
|
"Turn the command line output off.");
|
||||||
|
|
||||||
options.addOption(null, "skip-filter", false,
|
Option filterDoi = Option.builder().optionalArg(true).longOpt("filter").hasArg().argName("filterName")
|
||||||
"Skip the configured item filter when registering or reserving.");
|
.desc("Use the specified filter name instead of the provider's filter. Defaults to a special " +
|
||||||
|
"'always true' filter to force operations").build();
|
||||||
|
options.addOption(filterDoi);
|
||||||
|
|
||||||
Option registerDoi = Option.builder()
|
Option registerDoi = Option.builder()
|
||||||
.longOpt("register-doi")
|
.longOpt("register-doi")
|
||||||
@@ -203,10 +209,12 @@ public class DOIOrganiser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DOIService doiService = IdentifierServiceFactory.getInstance().getDOIService();
|
DOIService doiService = IdentifierServiceFactory.getInstance().getDOIService();
|
||||||
// Should we skip the filter?
|
// Do we get a filter?
|
||||||
if (line.hasOption("skip-filter")) {
|
if (line.hasOption("filter")) {
|
||||||
System.out.println("Skipping the item filter");
|
String filter = line.getOptionValue("filter");
|
||||||
organiser.skipFilter = true;
|
if (null != filter) {
|
||||||
|
organiser.filter = FilterUtils.getFilterFromConfiguration(filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.hasOption('s')) {
|
if (line.hasOption('s')) {
|
||||||
@@ -394,19 +402,18 @@ public class DOIOrganiser {
|
|||||||
/**
|
/**
|
||||||
* Register DOI with the provider
|
* Register DOI with the provider
|
||||||
* @param doiRow - doi to register
|
* @param doiRow - doi to register
|
||||||
* @param skipFilter - whether filters should be skipped before registration
|
* @param filter - logical item filter to override
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
* @throws DOIIdentifierException
|
* @throws DOIIdentifierException
|
||||||
*/
|
*/
|
||||||
public void register(DOI doiRow, boolean skipFilter) throws SQLException, DOIIdentifierException {
|
public void register(DOI doiRow, Filter filter) throws SQLException, DOIIdentifierException {
|
||||||
DSpaceObject dso = doiRow.getDSpaceObject();
|
DSpaceObject dso = doiRow.getDSpaceObject();
|
||||||
if (Constants.ITEM != dso.getType()) {
|
if (Constants.ITEM != dso.getType()) {
|
||||||
throw new IllegalArgumentException("Currenty DSpace supports DOIs for Items only.");
|
throw new IllegalArgumentException("Currenty DSpace supports DOIs for Items only.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
provider.registerOnline(context, dso,
|
provider.registerOnline(context, dso, DOI.SCHEME + doiRow.getDoi(), filter);
|
||||||
DOI.SCHEME + doiRow.getDoi());
|
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
System.out.println("This identifier: "
|
System.out.println("This identifier: "
|
||||||
@@ -466,29 +473,23 @@ public class DOIOrganiser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register DOI with the provider, always applying (ie. never skipping) any configured filters
|
* Register DOI with the provider
|
||||||
* @param doiRow - doi to register
|
* @param doiRow - doi to register
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
* @throws DOIIdentifierException
|
* @throws DOIIdentifierException
|
||||||
*/
|
*/
|
||||||
public void register(DOI doiRow) throws SQLException, DOIIdentifierException {
|
public void register(DOI doiRow) throws SQLException, DOIIdentifierException {
|
||||||
if (this.skipFilter) {
|
register(doiRow, this.filter);
|
||||||
System.out.println("Skipping the filter for " + doiRow.getDoi());
|
|
||||||
}
|
|
||||||
register(doiRow, this.skipFilter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserve DOI with the provider, always applying (ie. never skipping) any configured filters
|
* Reserve DOI with the provider,
|
||||||
* @param doiRow - doi to reserve
|
* @param doiRow - doi to reserve
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
* @throws DOIIdentifierException
|
* @throws DOIIdentifierException
|
||||||
*/
|
*/
|
||||||
public void reserve(DOI doiRow) {
|
public void reserve(DOI doiRow) {
|
||||||
if (this.skipFilter) {
|
reserve(doiRow, this.filter);
|
||||||
System.out.println("Skipping the filter for " + doiRow.getDoi());
|
|
||||||
}
|
|
||||||
reserve(doiRow, this.skipFilter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -497,14 +498,14 @@ public class DOIOrganiser {
|
|||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
* @throws DOIIdentifierException
|
* @throws DOIIdentifierException
|
||||||
*/
|
*/
|
||||||
public void reserve(DOI doiRow, boolean skipFilter) {
|
public void reserve(DOI doiRow, Filter filter) {
|
||||||
DSpaceObject dso = doiRow.getDSpaceObject();
|
DSpaceObject dso = doiRow.getDSpaceObject();
|
||||||
if (Constants.ITEM != dso.getType()) {
|
if (Constants.ITEM != dso.getType()) {
|
||||||
throw new IllegalArgumentException("Currently DSpace supports DOIs for Items only.");
|
throw new IllegalArgumentException("Currently DSpace supports DOIs for Items only.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
provider.reserveOnline(context, dso, DOI.SCHEME + doiRow.getDoi(), skipFilter);
|
provider.reserveOnline(context, dso, DOI.SCHEME + doiRow.getDoi(), filter);
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
System.out.println("This identifier : " + DOI.SCHEME + doiRow.getDoi() + " is successfully reserved.");
|
System.out.println("This identifier : " + DOI.SCHEME + doiRow.getDoi() + " is successfully reserved.");
|
||||||
@@ -699,7 +700,7 @@ public class DOIOrganiser {
|
|||||||
|
|
||||||
//Check if this Item has an Identifier, mint one if it doesn't
|
//Check if this Item has an Identifier, mint one if it doesn't
|
||||||
if (null == doiRow) {
|
if (null == doiRow) {
|
||||||
doi = provider.mint(context, dso, this.skipFilter);
|
doi = provider.mint(context, dso, this.filter);
|
||||||
doiRow = doiService.findByDoi(context,
|
doiRow = doiService.findByDoi(context,
|
||||||
doi.substring(DOI.SCHEME.length()));
|
doi.substring(DOI.SCHEME.length()));
|
||||||
return doiRow;
|
return doiRow;
|
||||||
@@ -723,7 +724,7 @@ public class DOIOrganiser {
|
|||||||
doiRow = doiService.findDOIByDSpaceObject(context, dso);
|
doiRow = doiService.findDOIByDSpaceObject(context, dso);
|
||||||
|
|
||||||
if (null == doiRow) {
|
if (null == doiRow) {
|
||||||
doi = provider.mint(context, dso, this.skipFilter);
|
doi = provider.mint(context, dso, this.filter);
|
||||||
doiRow = doiService.findByDoi(context,
|
doiRow = doiService.findByDoi(context,
|
||||||
doi.substring(DOI.SCHEME.length()));
|
doi.substring(DOI.SCHEME.length()));
|
||||||
}
|
}
|
||||||
|
@@ -9,9 +9,11 @@ package org.dspace.identifier.service;
|
|||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.logic.Filter;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.identifier.Identifier;
|
import org.dspace.identifier.Identifier;
|
||||||
import org.dspace.identifier.IdentifierException;
|
import org.dspace.identifier.IdentifierException;
|
||||||
@@ -103,6 +105,52 @@ public interface IdentifierService {
|
|||||||
*/
|
*/
|
||||||
void register(Context context, DSpaceObject dso) throws AuthorizeException, SQLException, IdentifierException;
|
void register(Context context, DSpaceObject dso) throws AuthorizeException, SQLException, IdentifierException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Register identifiers for a DSO, with a map of logical filters for each Identifier class to apply
|
||||||
|
* at the time of local registration.
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace Context.
|
||||||
|
* @param dso DSpace object to be registered
|
||||||
|
* @param typeFilters If a service supports a given Identifier implementation, apply the associated filter
|
||||||
|
* @throws AuthorizeException if authorization error
|
||||||
|
* @throws SQLException if database error
|
||||||
|
* @throws IdentifierException if identifier error
|
||||||
|
*/
|
||||||
|
void register(Context context, DSpaceObject dso, Map<Class<? extends Identifier>, Filter> typeFilters)
|
||||||
|
throws AuthorizeException, SQLException, IdentifierException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Register identifier(s) for the given DSO just with providers that support that Identifier class, and
|
||||||
|
* apply the given filter if that provider extends FilteredIdentifierProvider
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace Context.
|
||||||
|
* @param dso DSpace object to be registered
|
||||||
|
* @param type Type of identifier to register
|
||||||
|
* @param filter If a service supports a given Identifier implementation, apply this specific filter
|
||||||
|
* @throws AuthorizeException if authorization error
|
||||||
|
* @throws SQLException if database error
|
||||||
|
* @throws IdentifierException if identifier error
|
||||||
|
*/
|
||||||
|
void register(Context context, DSpaceObject dso, Class<? extends Identifier> type, Filter filter)
|
||||||
|
throws AuthorizeException, SQLException, IdentifierException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Register identifier(s) for the given DSO just with providers that support that Identifier class, and
|
||||||
|
* apply the given filter if that provider extends FilteredIdentifierProvider
|
||||||
|
*
|
||||||
|
* @param context The relevant DSpace Context.
|
||||||
|
* @param dso DSpace object to be registered
|
||||||
|
* @param type Type of identifier to register
|
||||||
|
* @throws AuthorizeException if authorization error
|
||||||
|
* @throws SQLException if database error
|
||||||
|
* @throws IdentifierException if identifier error
|
||||||
|
*/
|
||||||
|
void register(Context context, DSpaceObject dso, Class<? extends Identifier> type)
|
||||||
|
throws AuthorizeException, SQLException, IdentifierException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to Register a specific Identifier (for example a Handle, hdl:1234.5/6).
|
* Used to Register a specific Identifier (for example a Handle, hdl:1234.5/6).
|
||||||
* The provider is responsible for detecting and processing the appropriate
|
* The provider is responsible for detecting and processing the appropriate
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
package org.dspace.scripts;
|
package org.dspace.scripts;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -36,7 +37,9 @@ public class ScriptServiceImpl implements ScriptService {
|
|||||||
@Override
|
@Override
|
||||||
public List<ScriptConfiguration> getScriptConfigurations(Context context) {
|
public List<ScriptConfiguration> getScriptConfigurations(Context context) {
|
||||||
return serviceManager.getServicesByType(ScriptConfiguration.class).stream().filter(
|
return serviceManager.getServicesByType(ScriptConfiguration.class).stream().filter(
|
||||||
scriptConfiguration -> scriptConfiguration.isAllowedToExecute(context)).collect(Collectors.toList());
|
scriptConfiguration -> scriptConfiguration.isAllowedToExecute(context))
|
||||||
|
.sorted(Comparator.comparing(ScriptConfiguration::getName))
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -303,6 +303,10 @@ public class BitstreamStorageServiceImpl implements BitstreamStorageService, Ini
|
|||||||
commitCounter++;
|
commitCounter++;
|
||||||
if (commitCounter % 100 == 0) {
|
if (commitCounter % 100 == 0) {
|
||||||
context.dispatchEvents();
|
context.dispatchEvents();
|
||||||
|
// Commit actual changes to DB after dispatch events
|
||||||
|
System.out.print("Performing incremental commit to the database...");
|
||||||
|
context.commit();
|
||||||
|
System.out.println(" Incremental commit done!");
|
||||||
}
|
}
|
||||||
|
|
||||||
context.uncacheEntity(bitstream);
|
context.uncacheEntity(bitstream);
|
||||||
|
@@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
import static org.apache.commons.lang.StringUtils.EMPTY;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.crosswalk.StreamDisseminationCrosswalk;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.core.Email;
|
||||||
|
import org.dspace.core.I18nUtil;
|
||||||
|
import org.dspace.discovery.IndexableObject;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.subscriptions.service.SubscriptionGenerator;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation class of SubscriptionGenerator
|
||||||
|
* which will handle the logic of sending the emails
|
||||||
|
* in case of 'content' subscriptionType
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public class ContentGenerator implements SubscriptionGenerator<IndexableObject> {
|
||||||
|
|
||||||
|
private final Logger log = LogManager.getLogger(ContentGenerator.class);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map<String, StreamDisseminationCrosswalk> entityType2Disseminator = new HashMap();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ItemService itemService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyForSubscriptions(Context context, EPerson ePerson,
|
||||||
|
List<IndexableObject> indexableComm,
|
||||||
|
List<IndexableObject> indexableColl) {
|
||||||
|
try {
|
||||||
|
if (Objects.nonNull(ePerson)) {
|
||||||
|
Locale supportedLocale = I18nUtil.getEPersonLocale(ePerson);
|
||||||
|
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "subscriptions_content"));
|
||||||
|
email.addRecipient(ePerson.getEmail());
|
||||||
|
email.addArgument(generateBodyMail(context, indexableComm));
|
||||||
|
email.addArgument(generateBodyMail(context, indexableColl));
|
||||||
|
email.send();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
log.warn("Cannot email user eperson_id: {} eperson_email: {}", ePerson::getID, ePerson::getEmail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateBodyMail(Context context, List<IndexableObject> indexableObjects) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
out.write("\n".getBytes(UTF_8));
|
||||||
|
if (indexableObjects.size() > 0) {
|
||||||
|
for (IndexableObject indexableObject : indexableObjects) {
|
||||||
|
out.write("\n".getBytes(UTF_8));
|
||||||
|
Item item = (Item) indexableObject.getIndexedObject();
|
||||||
|
String entityType = itemService.getEntityTypeLabel(item);
|
||||||
|
Optional.ofNullable(entityType2Disseminator.get(entityType))
|
||||||
|
.orElseGet(() -> entityType2Disseminator.get("Item"))
|
||||||
|
.disseminate(context, item, out);
|
||||||
|
}
|
||||||
|
return out.toString();
|
||||||
|
} else {
|
||||||
|
out.write("No items".getBytes(UTF_8));
|
||||||
|
}
|
||||||
|
return out.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEntityType2Disseminator(Map<String, StreamDisseminationCrosswalk> entityType2Disseminator) {
|
||||||
|
this.entityType2Disseminator = entityType2Disseminator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.ParseException;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.eperson.FrequencyType;
|
||||||
|
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link DSpaceRunnable} to find subscribed objects and send notification mails about them
|
||||||
|
*
|
||||||
|
* @author alba aliu
|
||||||
|
*/
|
||||||
|
public class SubscriptionEmailNotification
|
||||||
|
extends DSpaceRunnable<SubscriptionEmailNotificationConfiguration<SubscriptionEmailNotification>> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
private SubscriptionEmailNotificationService subscriptionEmailNotificationService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public SubscriptionEmailNotificationConfiguration<SubscriptionEmailNotification> getScriptConfiguration() {
|
||||||
|
return new DSpace().getServiceManager().getServiceByName("subscription-send",
|
||||||
|
SubscriptionEmailNotificationConfiguration.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setup() throws ParseException {
|
||||||
|
this.subscriptionEmailNotificationService = new DSpace().getServiceManager().getServiceByName(
|
||||||
|
SubscriptionEmailNotificationServiceImpl.class.getName(), SubscriptionEmailNotificationServiceImpl.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void internalRun() throws Exception {
|
||||||
|
assignCurrentUserInContext();
|
||||||
|
assignSpecialGroupsInContext();
|
||||||
|
String frequencyOption = commandLine.getOptionValue("f");
|
||||||
|
if (StringUtils.isBlank(frequencyOption)) {
|
||||||
|
throw new IllegalArgumentException("Option --frequency (-f) must be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FrequencyType.isSupportedFrequencyType(frequencyOption)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Option f must be one of following values D(Day), W(Week) or M(Month)");
|
||||||
|
}
|
||||||
|
subscriptionEmailNotificationService.perform(getContext(), handler, "content", frequencyOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assignCurrentUserInContext() throws SQLException {
|
||||||
|
context = new Context();
|
||||||
|
UUID uuid = getEpersonIdentifier();
|
||||||
|
if (Objects.nonNull(uuid)) {
|
||||||
|
EPerson ePerson = EPersonServiceFactory.getInstance().getEPersonService().find(context, uuid);
|
||||||
|
context.setCurrentUser(ePerson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assignSpecialGroupsInContext() throws SQLException {
|
||||||
|
for (UUID uuid : handler.getSpecialGroups()) {
|
||||||
|
context.setSpecialGroup(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscriptionEmailNotificationService getSubscriptionEmailNotificationService() {
|
||||||
|
return subscriptionEmailNotificationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubscriptionEmailNotificationService(SubscriptionEmailNotificationService notificationService) {
|
||||||
|
this.subscriptionEmailNotificationService = notificationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Context getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContext(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link SubscriptionEmailNotification} for CLI.
|
||||||
|
*/
|
||||||
|
public class SubscriptionEmailNotificationCli extends SubscriptionEmailNotification {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link SubscriptionEmailNotificationCli} for CLI.
|
||||||
|
*/
|
||||||
|
public class SubscriptionEmailNotificationCliScriptConfiguration<T extends SubscriptionEmailNotificationCli>
|
||||||
|
extends SubscriptionEmailNotificationConfiguration<T> {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.authorize.AuthorizeServiceImpl;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link DSpaceRunnable} to find subscribed objects and send notification mails about them
|
||||||
|
*/
|
||||||
|
public class SubscriptionEmailNotificationConfiguration<T
|
||||||
|
extends SubscriptionEmailNotification> extends ScriptConfiguration<T> {
|
||||||
|
|
||||||
|
private Class<T> dspaceRunnableClass;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeServiceImpl authorizeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowedToExecute(Context context) {
|
||||||
|
try {
|
||||||
|
return authorizeService.isAdmin(context);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException("SQLException occurred when checking if the current user is an admin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Options getOptions() {
|
||||||
|
if (Objects.isNull(options)) {
|
||||||
|
Options options = new Options();
|
||||||
|
options.addOption("f", "frequency", true,
|
||||||
|
"Subscription frequency. Valid values include: D (Day), W (Week) and M (Month)");
|
||||||
|
options.getOption("f").setRequired(true);
|
||||||
|
super.options = options;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getDspaceRunnableClass() {
|
||||||
|
return dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
|
||||||
|
this.dspaceRunnableClass = dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service interface class for the subscription e-mail notification services
|
||||||
|
*
|
||||||
|
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||||
|
*/
|
||||||
|
public interface SubscriptionEmailNotificationService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs sending of e-mails to subscribers by frequency value and SubscriptionType
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param handler Applicable DSpaceRunnableHandler
|
||||||
|
* @param subscriptionType Currently supported only "content"
|
||||||
|
* @param frequency Valid values include: D (Day), W (Week) and M (Month)
|
||||||
|
*/
|
||||||
|
public void perform(Context context, DSpaceRunnableHandler handler, String subscriptionType, String frequency);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a set of supported SubscriptionTypes
|
||||||
|
*/
|
||||||
|
public Set<String> getSupportedSubscriptionTypes();
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions;
|
||||||
|
|
||||||
|
import static org.dspace.core.Constants.COLLECTION;
|
||||||
|
import static org.dspace.core.Constants.COMMUNITY;
|
||||||
|
import static org.dspace.core.Constants.READ;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.discovery.IndexableObject;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.eperson.Subscription;
|
||||||
|
import org.dspace.eperson.service.SubscribeService;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||||
|
import org.dspace.subscriptions.service.DSpaceObjectUpdates;
|
||||||
|
import org.dspace.subscriptions.service.SubscriptionGenerator;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link DSpaceRunnable} to find subscribed objects and send notification mails about them
|
||||||
|
*
|
||||||
|
* @author alba aliu
|
||||||
|
*/
|
||||||
|
public class SubscriptionEmailNotificationServiceImpl implements SubscriptionEmailNotificationService {
|
||||||
|
|
||||||
|
private static final Logger log = LogManager.getLogger(SubscriptionEmailNotificationServiceImpl.class);
|
||||||
|
|
||||||
|
private Map<String, DSpaceObjectUpdates> contentUpdates = new HashMap<>();
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private Map<String, SubscriptionGenerator> subscriptionType2generators = new HashMap<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
@Autowired
|
||||||
|
private SubscribeService subscribeService;
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public SubscriptionEmailNotificationServiceImpl(Map<String, DSpaceObjectUpdates> contentUpdates,
|
||||||
|
Map<String, SubscriptionGenerator> subscriptionType2generators) {
|
||||||
|
this.contentUpdates = contentUpdates;
|
||||||
|
this.subscriptionType2generators = subscriptionType2generators;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
public void perform(Context context, DSpaceRunnableHandler handler, String subscriptionType, String frequency) {
|
||||||
|
List<IndexableObject> communityItems = new ArrayList<>();
|
||||||
|
List<IndexableObject> collectionsItems = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
List<Subscription> subscriptions =
|
||||||
|
findAllSubscriptionsBySubscriptionTypeAndFrequency(context, subscriptionType, frequency);
|
||||||
|
// Here is verified if SubscriptionType is "content" Or "statistics" as them are configured
|
||||||
|
if (subscriptionType2generators.keySet().contains(subscriptionType)) {
|
||||||
|
// the list of the person who has subscribed
|
||||||
|
int iterator = 0;
|
||||||
|
for (Subscription subscription : subscriptions) {
|
||||||
|
DSpaceObject dSpaceObject = subscription.getDSpaceObject();
|
||||||
|
EPerson ePerson = subscription.getEPerson();
|
||||||
|
|
||||||
|
if (!authorizeService.authorizeActionBoolean(context, ePerson, dSpaceObject, READ, true)) {
|
||||||
|
iterator++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dSpaceObject.getType() == COMMUNITY) {
|
||||||
|
List<IndexableObject> indexableCommunityItems = contentUpdates
|
||||||
|
.get(Community.class.getSimpleName().toLowerCase())
|
||||||
|
.findUpdates(context, dSpaceObject, frequency);
|
||||||
|
communityItems.addAll(getItems(context, ePerson, indexableCommunityItems));
|
||||||
|
} else if (dSpaceObject.getType() == COLLECTION) {
|
||||||
|
List<IndexableObject> indexableCollectionItems = contentUpdates
|
||||||
|
.get(Collection.class.getSimpleName().toLowerCase())
|
||||||
|
.findUpdates(context, dSpaceObject, frequency);
|
||||||
|
collectionsItems.addAll(getItems(context, ePerson, indexableCollectionItems));
|
||||||
|
} else {
|
||||||
|
log.warn("found an invalid DSpace Object type ({}) among subscriptions to send",
|
||||||
|
dSpaceObject.getType());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iterator < subscriptions.size() - 1) {
|
||||||
|
// as the subscriptions are ordered by eperson id, so we send them by ePerson
|
||||||
|
if (ePerson.equals(subscriptions.get(iterator + 1).getEPerson())) {
|
||||||
|
iterator++;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
subscriptionType2generators.get(subscriptionType)
|
||||||
|
.notifyForSubscriptions(context, ePerson, communityItems, collectionsItems);
|
||||||
|
communityItems.clear();
|
||||||
|
collectionsItems.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//in the end of the iteration
|
||||||
|
subscriptionType2generators.get(subscriptionType)
|
||||||
|
.notifyForSubscriptions(context, ePerson, communityItems, collectionsItems);
|
||||||
|
}
|
||||||
|
iterator++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Currently this SubscriptionType:" + subscriptionType +
|
||||||
|
" is not supported!");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
handler.handleException(e);
|
||||||
|
context.abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private List<IndexableObject> getItems(Context context, EPerson ePerson, List<IndexableObject> indexableItems)
|
||||||
|
throws SQLException {
|
||||||
|
List<IndexableObject> items = new ArrayList<IndexableObject>();
|
||||||
|
for (IndexableObject indexableitem : indexableItems) {
|
||||||
|
Item item = (Item) indexableitem.getIndexedObject();
|
||||||
|
if (authorizeService.authorizeActionBoolean(context, ePerson, item, READ, true)) {
|
||||||
|
items.add(indexableitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all Subscriptions by subscriptionType and frequency ordered by ePerson ID
|
||||||
|
* if there are none it returns an empty list
|
||||||
|
*
|
||||||
|
* @param context DSpace context
|
||||||
|
* @param subscriptionType Could be "content" or "statistics". NOTE: in DSpace we have only "content"
|
||||||
|
* @param frequency Could be "D" stand for Day, "W" stand for Week, and "M" stand for Month
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<Subscription> findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
|
||||||
|
String subscriptionType, String frequency) {
|
||||||
|
try {
|
||||||
|
return subscribeService.findAllSubscriptionsBySubscriptionTypeAndFrequency(context, subscriptionType,
|
||||||
|
frequency)
|
||||||
|
.stream()
|
||||||
|
.sorted(Comparator.comparing(s -> s.getEPerson().getID()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return new ArrayList<Subscription>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getSupportedSubscriptionTypes() {
|
||||||
|
return subscriptionType2generators.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions.objectupdates;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.discovery.DiscoverQuery;
|
||||||
|
import org.dspace.discovery.DiscoverResult;
|
||||||
|
import org.dspace.discovery.IndexableObject;
|
||||||
|
import org.dspace.discovery.SearchService;
|
||||||
|
import org.dspace.discovery.SearchServiceException;
|
||||||
|
import org.dspace.eperson.FrequencyType;
|
||||||
|
import org.dspace.subscriptions.service.DSpaceObjectUpdates;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which will be used to find
|
||||||
|
* all collection objects updated related with subscribed DSO
|
||||||
|
*
|
||||||
|
* @author Alba Aliu
|
||||||
|
*/
|
||||||
|
public class CollectionUpdates implements DSpaceObjectUpdates {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SearchService searchService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public List<IndexableObject> findUpdates(Context context, DSpaceObject dSpaceObject, String frequency)
|
||||||
|
throws SearchServiceException {
|
||||||
|
DiscoverQuery discoverQuery = new DiscoverQuery();
|
||||||
|
getDefaultFilterQueries().stream().forEach(fq -> discoverQuery.addFilterQueries(fq));
|
||||||
|
discoverQuery.addFilterQueries("location.coll:(" + dSpaceObject.getID() + ")");
|
||||||
|
discoverQuery.addFilterQueries("lastModified:" + FrequencyType.findLastFrequency(frequency));
|
||||||
|
DiscoverResult discoverResult = searchService.search(context, discoverQuery);
|
||||||
|
return discoverResult.getIndexableObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions.objectupdates;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.discovery.DiscoverQuery;
|
||||||
|
import org.dspace.discovery.DiscoverResult;
|
||||||
|
import org.dspace.discovery.IndexableObject;
|
||||||
|
import org.dspace.discovery.SearchService;
|
||||||
|
import org.dspace.discovery.SearchServiceException;
|
||||||
|
import org.dspace.eperson.FrequencyType;
|
||||||
|
import org.dspace.subscriptions.service.DSpaceObjectUpdates;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which will be used to find
|
||||||
|
* all community objects updated related with subscribed DSO
|
||||||
|
*
|
||||||
|
* @author Alba Aliu
|
||||||
|
*/
|
||||||
|
public class CommunityUpdates implements DSpaceObjectUpdates {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SearchService searchService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public List<IndexableObject> findUpdates(Context context, DSpaceObject dSpaceObject, String frequency)
|
||||||
|
throws SearchServiceException {
|
||||||
|
DiscoverQuery discoverQuery = new DiscoverQuery();
|
||||||
|
getDefaultFilterQueries().stream().forEach(fq -> discoverQuery.addFilterQueries(fq));
|
||||||
|
discoverQuery.addFilterQueries("location.comm:(" + dSpaceObject.getID() + ")");
|
||||||
|
discoverQuery.addFilterQueries("lastModified:" + FrequencyType.findLastFrequency(frequency));
|
||||||
|
DiscoverResult discoverResult = searchService.search(context, discoverQuery);
|
||||||
|
return discoverResult.getIndexableObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.subscriptions.service;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.discovery.IndexableObject;
|
||||||
|
import org.dspace.discovery.SearchServiceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface class which will be used to find all objects updated related with subscribed DSO
|
||||||
|
*
|
||||||
|
* @author Alba Aliu
|
||||||
|
*/
|
||||||
|
public interface DSpaceObjectUpdates {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an email to some addresses, concerning a Subscription, using a given dso.
|
||||||
|
*
|
||||||
|
* @param context current DSpace session.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public List<IndexableObject> findUpdates(Context context, DSpaceObject dSpaceObject, String frequency)
|
||||||
|
throws SearchServiceException;
|
||||||
|
|
||||||
|
default List<String> getDefaultFilterQueries() {
|
||||||
|
return Arrays.asList("search.resourcetype:" + Item.class.getSimpleName(),
|
||||||
|
"-discoverable:" + false,
|
||||||
|
"-withdrawn:" + true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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.subscriptions.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface Class which will be used to send email notifications to ePerson
|
||||||
|
* containing information for all list of objects.
|
||||||
|
*
|
||||||
|
* @author Alba Aliu
|
||||||
|
*/
|
||||||
|
public interface SubscriptionGenerator<T> {
|
||||||
|
|
||||||
|
public void notifyForSubscriptions(Context c, EPerson ePerson, List<T> comm, List<T> coll);
|
||||||
|
|
||||||
|
}
|
@@ -18,6 +18,7 @@ import org.dspace.core.Context;
|
|||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.Group;
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
||||||
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service interface class for the WorkflowService framework.
|
* Service interface class for the WorkflowService framework.
|
||||||
@@ -100,6 +101,9 @@ public interface WorkflowService<T extends WorkflowItem> {
|
|||||||
String rejection_message)
|
String rejection_message)
|
||||||
throws SQLException, AuthorizeException, IOException;
|
throws SQLException, AuthorizeException, IOException;
|
||||||
|
|
||||||
|
public void restartWorkflow(Context context, XmlWorkflowItem wi, EPerson decliner, String provenance)
|
||||||
|
throws SQLException, AuthorizeException, IOException, WorkflowException;
|
||||||
|
|
||||||
public String getMyDSpaceLink();
|
public String getMyDSpaceLink();
|
||||||
|
|
||||||
public void deleteCollection(Context context, Collection collection)
|
public void deleteCollection(Context context, Collection collection)
|
||||||
|
@@ -41,6 +41,9 @@ public class Role implements BeanNameAware {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private WorkflowItemRoleService workflowItemRoleService;
|
private WorkflowItemRoleService workflowItemRoleService;
|
||||||
|
|
||||||
|
// Whether or not to delete temporary group made attached to the WorkflowItemRole for this role in AutoAssignAction
|
||||||
|
private boolean deleteTemporaryGroup = false;
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
@@ -153,4 +156,17 @@ public class Role implements BeanNameAware {
|
|||||||
public void setInternal(boolean internal) {
|
public void setInternal(boolean internal) {
|
||||||
isInternal = internal;
|
isInternal = internal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDeleteTemporaryGroup() {
|
||||||
|
return deleteTemporaryGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for config that indicated whether or not to delete temporary group made attached to the
|
||||||
|
* WorkflowItemRole for this role in AutoAssignAction
|
||||||
|
* @param deleteTemporaryGroup
|
||||||
|
*/
|
||||||
|
public void setDeleteTemporaryGroup(boolean deleteTemporaryGroup) {
|
||||||
|
this.deleteTemporaryGroup = deleteTemporaryGroup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1076,6 +1076,53 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
|
|||||||
return wsi;
|
return wsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restartWorkflow(Context context, XmlWorkflowItem wi, EPerson decliner, String provenance)
|
||||||
|
throws SQLException, AuthorizeException, IOException, WorkflowException {
|
||||||
|
if (!authorizeService.isAdmin(context)) {
|
||||||
|
throw new AuthorizeException("You must be an admin to restart a workflow");
|
||||||
|
}
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
// rejection provenance
|
||||||
|
Item myitem = wi.getItem();
|
||||||
|
|
||||||
|
// Here's what happened
|
||||||
|
String provDescription =
|
||||||
|
provenance + " Declined by " + getEPersonName(decliner) + " on " + DCDate.getCurrent().toString() +
|
||||||
|
" (GMT) ";
|
||||||
|
|
||||||
|
// Add to item as a DC field
|
||||||
|
itemService
|
||||||
|
.addMetadata(context, myitem, MetadataSchemaEnum.DC.getName(),
|
||||||
|
"description", "provenance", "en", provDescription);
|
||||||
|
|
||||||
|
//Clear any workflow schema related metadata
|
||||||
|
itemService
|
||||||
|
.clearMetadata(context, myitem, WorkflowRequirementsService.WORKFLOW_SCHEMA, Item.ANY, Item.ANY, Item.ANY);
|
||||||
|
|
||||||
|
itemService.update(context, myitem);
|
||||||
|
|
||||||
|
// remove policy for controller
|
||||||
|
removeUserItemPolicies(context, myitem, decliner);
|
||||||
|
revokeReviewerPolicies(context, myitem);
|
||||||
|
|
||||||
|
// convert into personal workspace
|
||||||
|
WorkspaceItem wsi = returnToWorkspace(context, wi);
|
||||||
|
|
||||||
|
// Because of issue of xmlWorkflowItemService not realising wfi wrapper has been deleted
|
||||||
|
context.commit();
|
||||||
|
wsi = context.reloadEntity(wsi);
|
||||||
|
|
||||||
|
log.info(LogHelper.getHeader(context, "decline_workflow", "workflow_item_id="
|
||||||
|
+ wi.getID() + "item_id=" + wi.getItem().getID() + "collection_id=" + wi.getCollection().getID() +
|
||||||
|
"eperson_id=" + decliner.getID()));
|
||||||
|
|
||||||
|
// Restart workflow
|
||||||
|
this.startWithoutNotify(context, wsi);
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the workflow item to the workspace of the submitter. The workflow
|
* Return the workflow item to the workspace of the submitter. The workflow
|
||||||
* item is removed, and a workspace item created.
|
* item is removed, and a workspace item created.
|
||||||
|
@@ -14,10 +14,15 @@ import java.util.List;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.content.DCDate;
|
||||||
|
import org.dspace.content.MetadataSchemaEnum;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.workflow.WorkflowException;
|
import org.dspace.workflow.WorkflowException;
|
||||||
import org.dspace.xmlworkflow.RoleMembers;
|
import org.dspace.xmlworkflow.RoleMembers;
|
||||||
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
import org.dspace.xmlworkflow.WorkflowConfigurationException;
|
||||||
|
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
import org.dspace.xmlworkflow.state.Step;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
|
|
||||||
@@ -37,6 +42,8 @@ public abstract class Action {
|
|||||||
|
|
||||||
private WorkflowActionConfig parent;
|
private WorkflowActionConfig parent;
|
||||||
private static final String ERROR_FIELDS_ATTRIBUTE = "dspace.workflow.error_fields";
|
private static final String ERROR_FIELDS_ATTRIBUTE = "dspace.workflow.error_fields";
|
||||||
|
private List<String> advancedOptions = new ArrayList<>();
|
||||||
|
private List<ActionAdvancedInfo> advancedInfo = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a workflow item becomes eligible for this Action.
|
* Called when a workflow item becomes eligible for this Action.
|
||||||
@@ -192,4 +199,58 @@ public abstract class Action {
|
|||||||
//save updated list
|
//save updated list
|
||||||
setErrorFields(request, errorFields);
|
setErrorFields(request, errorFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of advanced options that the user can select at this action
|
||||||
|
* @return A list of advanced options of this action, resulting in the next step of the workflow
|
||||||
|
*/
|
||||||
|
protected List<String> getAdvancedOptions() {
|
||||||
|
return advancedOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this Action has advanced options, false if it doesn't
|
||||||
|
* @return true if there are advanced options, false otherwise
|
||||||
|
*/
|
||||||
|
protected boolean isAdvanced() {
|
||||||
|
return !getAdvancedOptions().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of advanced info required by the advanced options
|
||||||
|
* @return A list of advanced info required by the advanced options
|
||||||
|
*/
|
||||||
|
protected List<ActionAdvancedInfo> getAdvancedInfo() {
|
||||||
|
return advancedInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds info in the metadata field dc.description.provenance about item being approved containing in which step
|
||||||
|
* it was approved, which user approved it and the time
|
||||||
|
*
|
||||||
|
* @param c DSpace contect
|
||||||
|
* @param wfi Workflow item we're adding workflow accept provenance on
|
||||||
|
*/
|
||||||
|
public void addApprovedProvenance(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
|
||||||
|
ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
|
||||||
|
//Add the provenance for the accept
|
||||||
|
String now = DCDate.getCurrent().toString();
|
||||||
|
|
||||||
|
// Get user's name + email address
|
||||||
|
String usersName =
|
||||||
|
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService().getEPersonName(c.getCurrentUser());
|
||||||
|
|
||||||
|
String provDescription = getProvenanceStartId() + " Approved for entry into archive by " + usersName + " on "
|
||||||
|
+ now + " (GMT) ";
|
||||||
|
|
||||||
|
// Add to item as a DC field
|
||||||
|
c.turnOffAuthorisationSystem();
|
||||||
|
itemService.addMetadata(c, wfi.getItem(), MetadataSchemaEnum.DC.getName(), "description", "provenance", "en",
|
||||||
|
provDescription);
|
||||||
|
itemService.update(c, wfi.getItem());
|
||||||
|
c.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* 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.xmlworkflow.state.actions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for the shared properties of an 'advancedInfo' section of an advanced workflow {@link Action}
|
||||||
|
* Implementations of this class will define the specific fields per action that will need to be defined/configured
|
||||||
|
* to pass along this info to REST endpoint
|
||||||
|
*/
|
||||||
|
public abstract class ActionAdvancedInfo {
|
||||||
|
|
||||||
|
protected String type;
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
protected final static String TYPE_PREFIX = "action_info_";
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = TYPE_PREFIX + type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for the Action id to be set.
|
||||||
|
* This is an MD5 hash of the type and the stringified properties of the advanced info
|
||||||
|
*
|
||||||
|
* @param type The type of this Action to be included in the MD5 hash
|
||||||
|
*/
|
||||||
|
protected abstract void generateId(String type);
|
||||||
|
|
||||||
|
}
|
@@ -69,4 +69,28 @@ public class WorkflowActionConfig {
|
|||||||
return this.processingAction.getOptions();
|
return this.processingAction.getOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of advanced options this user has on this action, resulting in the next step of the workflow
|
||||||
|
* @return A list of advanced options of this action, resulting in the next step of the workflow
|
||||||
|
*/
|
||||||
|
public List<String> getAdvancedOptions() {
|
||||||
|
return this.processingAction.getAdvancedOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean depending on whether this action has advanced options
|
||||||
|
* @return The boolean indicating whether this action has advanced options
|
||||||
|
*/
|
||||||
|
public boolean isAdvanced() {
|
||||||
|
return this.processingAction.isAdvanced();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Map of info for the advanced options this user has on this action
|
||||||
|
* @return a Map of info for the advanced options this user has on this action
|
||||||
|
*/
|
||||||
|
public List<ActionAdvancedInfo> getAdvancedInfo() {
|
||||||
|
return this.processingAction.getAdvancedInfo();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
import org.dspace.app.util.Util;
|
import org.dspace.app.util.Util;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.DCDate;
|
|
||||||
import org.dspace.content.MetadataSchemaEnum;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
import org.dspace.xmlworkflow.state.Step;
|
||||||
@@ -34,8 +32,6 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
|||||||
*/
|
*/
|
||||||
public class AcceptEditRejectAction extends ProcessingAction {
|
public class AcceptEditRejectAction extends ProcessingAction {
|
||||||
|
|
||||||
private static final String SUBMIT_APPROVE = "submit_approve";
|
|
||||||
private static final String SUBMIT_REJECT = "submit_reject";
|
|
||||||
private static final String SUBMITTER_IS_DELETED_PAGE = "submitter_deleted";
|
private static final String SUBMITTER_IS_DELETED_PAGE = "submitter_deleted";
|
||||||
|
|
||||||
//TODO: rename to AcceptAndEditMetadataAction
|
//TODO: rename to AcceptAndEditMetadataAction
|
||||||
@@ -53,7 +49,7 @@ public class AcceptEditRejectAction extends ProcessingAction {
|
|||||||
case SUBMIT_APPROVE:
|
case SUBMIT_APPROVE:
|
||||||
return processAccept(c, wfi);
|
return processAccept(c, wfi);
|
||||||
case SUBMIT_REJECT:
|
case SUBMIT_REJECT:
|
||||||
return processRejectPage(c, wfi, request);
|
return super.processRejectPage(c, wfi, request);
|
||||||
case SUBMITTER_IS_DELETED_PAGE:
|
case SUBMITTER_IS_DELETED_PAGE:
|
||||||
return processSubmitterIsDeletedPage(c, wfi, request);
|
return processSubmitterIsDeletedPage(c, wfi, request);
|
||||||
default:
|
default:
|
||||||
@@ -69,33 +65,18 @@ public class AcceptEditRejectAction extends ProcessingAction {
|
|||||||
options.add(SUBMIT_APPROVE);
|
options.add(SUBMIT_APPROVE);
|
||||||
options.add(SUBMIT_REJECT);
|
options.add(SUBMIT_REJECT);
|
||||||
options.add(ProcessingAction.SUBMIT_EDIT_METADATA);
|
options.add(ProcessingAction.SUBMIT_EDIT_METADATA);
|
||||||
|
options.add(RETURN_TO_POOL);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult processAccept(Context c, XmlWorkflowItem wfi)
|
public ActionResult processAccept(Context c, XmlWorkflowItem wfi)
|
||||||
throws SQLException, AuthorizeException {
|
throws SQLException, AuthorizeException {
|
||||||
//Delete the tasks
|
//Delete the tasks
|
||||||
addApprovedProvenance(c, wfi);
|
super.addApprovedProvenance(c, wfi);
|
||||||
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult processRejectPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
|
||||||
throws SQLException, AuthorizeException, IOException {
|
|
||||||
String reason = request.getParameter("reason");
|
|
||||||
if (reason == null || 0 == reason.trim().length()) {
|
|
||||||
addErrorField(request, "reason");
|
|
||||||
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);
|
|
||||||
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionResult processSubmitterIsDeletedPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
public ActionResult processSubmitterIsDeletedPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
||||||
throws SQLException, AuthorizeException, IOException {
|
throws SQLException, AuthorizeException, IOException {
|
||||||
if (request.getParameter("submit_delete") != null) {
|
if (request.getParameter("submit_delete") != null) {
|
||||||
@@ -111,21 +92,4 @@ public class AcceptEditRejectAction extends ProcessingAction {
|
|||||||
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
|
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addApprovedProvenance(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
|
|
||||||
//Add the provenance for the accept
|
|
||||||
String now = DCDate.getCurrent().toString();
|
|
||||||
|
|
||||||
// Get user's name + email address
|
|
||||||
String usersName = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
|
||||||
.getEPersonName(c.getCurrentUser());
|
|
||||||
|
|
||||||
String provDescription = getProvenanceStartId() + " Approved for entry into archive by "
|
|
||||||
+ usersName + " on " + now + " (GMT) ";
|
|
||||||
|
|
||||||
// Add to item as a DC field
|
|
||||||
itemService.addMetadata(c, wfi.getItem(), MetadataSchemaEnum.DC.getName(), "description", "provenance", "en",
|
|
||||||
provDescription);
|
|
||||||
itemService.update(c, wfi.getItem());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -14,10 +14,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
import org.dspace.app.util.Util;
|
import org.dspace.app.util.Util;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.DCDate;
|
|
||||||
import org.dspace.content.MetadataSchemaEnum;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
import org.dspace.xmlworkflow.state.Step;
|
||||||
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
@@ -52,7 +49,7 @@ public class FinalEditAction extends ProcessingAction {
|
|||||||
switch (Util.getSubmitButton(request, SUBMIT_CANCEL)) {
|
switch (Util.getSubmitButton(request, SUBMIT_CANCEL)) {
|
||||||
case SUBMIT_APPROVE:
|
case SUBMIT_APPROVE:
|
||||||
//Delete the tasks
|
//Delete the tasks
|
||||||
addApprovedProvenance(c, wfi);
|
super.addApprovedProvenance(c, wfi);
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
||||||
default:
|
default:
|
||||||
//We pressed the leave button so return to our submissions page
|
//We pressed the leave button so return to our submissions page
|
||||||
@@ -67,25 +64,8 @@ public class FinalEditAction extends ProcessingAction {
|
|||||||
List<String> options = new ArrayList<>();
|
List<String> options = new ArrayList<>();
|
||||||
options.add(SUBMIT_APPROVE);
|
options.add(SUBMIT_APPROVE);
|
||||||
options.add(ProcessingAction.SUBMIT_EDIT_METADATA);
|
options.add(ProcessingAction.SUBMIT_EDIT_METADATA);
|
||||||
|
options.add(RETURN_TO_POOL);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addApprovedProvenance(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
|
|
||||||
//Add the provenance for the accept
|
|
||||||
String now = DCDate.getCurrent().toString();
|
|
||||||
|
|
||||||
// Get user's name + email address
|
|
||||||
String usersName = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
|
||||||
.getEPersonName(c.getCurrentUser());
|
|
||||||
|
|
||||||
String provDescription = getProvenanceStartId() + " Approved for entry into archive by "
|
|
||||||
+ usersName + " on " + now + " (GMT) ";
|
|
||||||
|
|
||||||
// Add to item as a DC field
|
|
||||||
itemService.addMetadata(c, wfi.getItem(), MetadataSchemaEnum.DC.getName(), "description", "provenance", "en",
|
|
||||||
provDescription);
|
|
||||||
itemService.update(c, wfi.getItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,12 +7,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.xmlworkflow.state.actions.processingaction;
|
package org.dspace.xmlworkflow.state.actions.processingaction;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.xmlworkflow.service.XmlWorkflowService;
|
||||||
import org.dspace.xmlworkflow.state.actions.Action;
|
import org.dspace.xmlworkflow.state.actions.Action;
|
||||||
|
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
|
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService;
|
import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService;
|
||||||
@@ -32,9 +36,15 @@ public abstract class ProcessingAction extends Action {
|
|||||||
protected ClaimedTaskService claimedTaskService;
|
protected ClaimedTaskService claimedTaskService;
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected ItemService itemService;
|
protected ItemService itemService;
|
||||||
|
@Autowired
|
||||||
|
protected XmlWorkflowService xmlWorkflowService;
|
||||||
|
|
||||||
public static final String SUBMIT_EDIT_METADATA = "submit_edit_metadata";
|
public static final String SUBMIT_EDIT_METADATA = "submit_edit_metadata";
|
||||||
public static final String SUBMIT_CANCEL = "submit_cancel";
|
public static final String SUBMIT_CANCEL = "submit_cancel";
|
||||||
|
protected static final String SUBMIT_APPROVE = "submit_approve";
|
||||||
|
protected static final String SUBMIT_REJECT = "submit_reject";
|
||||||
|
protected static final String RETURN_TO_POOL = "return_to_pool";
|
||||||
|
protected static final String REJECT_REASON = "reason";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAuthorized(Context context, HttpServletRequest request, XmlWorkflowItem wfi) throws SQLException {
|
public boolean isAuthorized(Context context, HttpServletRequest request, XmlWorkflowItem wfi) throws SQLException {
|
||||||
@@ -48,4 +58,31 @@ public abstract class ProcessingAction extends Action {
|
|||||||
task.getStepID().equals(getParent().getStep().getId()) &&
|
task.getStepID().equals(getParent().getStep().getId()) &&
|
||||||
task.getActionID().equals(getParent().getId());
|
task.getActionID().equals(getParent().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process result when option {@link this#SUBMIT_REJECT} is selected.
|
||||||
|
* - Sets the reason and workflow step responsible on item in dc.description.provenance
|
||||||
|
* - Send workflow back to the submission
|
||||||
|
* If reason is not given => error
|
||||||
|
*/
|
||||||
|
public ActionResult processRejectPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
||||||
|
throws SQLException, AuthorizeException, IOException {
|
||||||
|
String reason = request.getParameter(REJECT_REASON);
|
||||||
|
if (reason == null || 0 == reason.trim().length()) {
|
||||||
|
addErrorField(request, REJECT_REASON);
|
||||||
|
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
|
||||||
|
xmlWorkflowService.sendWorkflowItemBackSubmission(c, wfi, c.getCurrentUser(), this.getProvenanceStartId(),
|
||||||
|
reason);
|
||||||
|
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isAdvanced() {
|
||||||
|
return !getAdvancedOptions().isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
import org.dspace.app.util.Util;
|
import org.dspace.app.util.Util;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.DCDate;
|
|
||||||
import org.dspace.content.MetadataSchemaEnum;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
import org.dspace.xmlworkflow.state.Step;
|
||||||
@@ -36,11 +34,8 @@ public class ReviewAction extends ProcessingAction {
|
|||||||
public static final int MAIN_PAGE = 0;
|
public static final int MAIN_PAGE = 0;
|
||||||
public static final int REJECT_PAGE = 1;
|
public static final int REJECT_PAGE = 1;
|
||||||
|
|
||||||
private static final String SUBMIT_APPROVE = "submit_approve";
|
|
||||||
private static final String SUBMIT_REJECT = "submit_reject";
|
|
||||||
private static final String SUBMITTER_IS_DELETED_PAGE = "submitter_deleted";
|
private static final String SUBMITTER_IS_DELETED_PAGE = "submitter_deleted";
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activate(Context c, XmlWorkflowItem wfItem) {
|
public void activate(Context c, XmlWorkflowItem wfItem) {
|
||||||
|
|
||||||
@@ -54,7 +49,7 @@ public class ReviewAction extends ProcessingAction {
|
|||||||
case SUBMIT_APPROVE:
|
case SUBMIT_APPROVE:
|
||||||
return processAccept(c, wfi);
|
return processAccept(c, wfi);
|
||||||
case SUBMIT_REJECT:
|
case SUBMIT_REJECT:
|
||||||
return processRejectPage(c, wfi, step, request);
|
return super.processRejectPage(c, wfi, request);
|
||||||
case SUBMITTER_IS_DELETED_PAGE:
|
case SUBMITTER_IS_DELETED_PAGE:
|
||||||
return processSubmitterIsDeletedPage(c, wfi, request);
|
return processSubmitterIsDeletedPage(c, wfi, request);
|
||||||
default:
|
default:
|
||||||
@@ -69,50 +64,15 @@ public class ReviewAction extends ProcessingAction {
|
|||||||
List<String> options = new ArrayList<>();
|
List<String> options = new ArrayList<>();
|
||||||
options.add(SUBMIT_APPROVE);
|
options.add(SUBMIT_APPROVE);
|
||||||
options.add(SUBMIT_REJECT);
|
options.add(SUBMIT_REJECT);
|
||||||
|
options.add(RETURN_TO_POOL);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult processAccept(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
|
public ActionResult processAccept(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
|
||||||
//Delete the tasks
|
super.addApprovedProvenance(c, wfi);
|
||||||
addApprovedProvenance(c, wfi);
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addApprovedProvenance(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
|
|
||||||
//Add the provenance for the accept
|
|
||||||
String now = DCDate.getCurrent().toString();
|
|
||||||
|
|
||||||
// Get user's name + email address
|
|
||||||
String usersName = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
|
||||||
.getEPersonName(c.getCurrentUser());
|
|
||||||
|
|
||||||
String provDescription = getProvenanceStartId() + " Approved for entry into archive by "
|
|
||||||
+ usersName + " on " + now + " (GMT) ";
|
|
||||||
|
|
||||||
// Add to item as a DC field
|
|
||||||
itemService.addMetadata(c, wfi.getItem(), MetadataSchemaEnum.DC.getName(), "description", "provenance", "en",
|
|
||||||
provDescription);
|
|
||||||
itemService.update(c, wfi.getItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionResult processRejectPage(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
|
||||||
throws SQLException, AuthorizeException, IOException {
|
|
||||||
String reason = request.getParameter("reason");
|
|
||||||
if (reason == null || 0 == reason.trim().length()) {
|
|
||||||
request.setAttribute("page", REJECT_PAGE);
|
|
||||||
addErrorField(request, "reason");
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionResult processSubmitterIsDeletedPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
public ActionResult processSubmitterIsDeletedPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
||||||
throws SQLException, AuthorizeException, IOException {
|
throws SQLException, AuthorizeException, IOException {
|
||||||
if (request.getParameter("submit_delete") != null) {
|
if (request.getParameter("submit_delete") != null) {
|
||||||
|
@@ -7,6 +7,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.xmlworkflow.state.actions.processingaction;
|
package org.dspace.xmlworkflow.state.actions.processingaction;
|
||||||
|
|
||||||
|
import static org.dspace.xmlworkflow.state.actions.processingaction.ScoreReviewAction.REVIEW_FIELD;
|
||||||
|
import static org.dspace.xmlworkflow.state.actions.processingaction.ScoreReviewAction.SCORE_FIELD;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -19,7 +22,6 @@ import org.dspace.content.MetadataSchemaEnum;
|
|||||||
import org.dspace.content.MetadataValue;
|
import org.dspace.content.MetadataValue;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
||||||
import org.dspace.xmlworkflow.service.WorkflowRequirementsService;
|
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
import org.dspace.xmlworkflow.state.Step;
|
||||||
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
@@ -37,6 +39,7 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
|||||||
*/
|
*/
|
||||||
public class ScoreEvaluationAction extends ProcessingAction {
|
public class ScoreEvaluationAction extends ProcessingAction {
|
||||||
|
|
||||||
|
// Minimum aggregate of scores
|
||||||
private int minimumAcceptanceScore;
|
private int minimumAcceptanceScore;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -47,43 +50,64 @@ public class ScoreEvaluationAction extends ProcessingAction {
|
|||||||
@Override
|
@Override
|
||||||
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
||||||
throws SQLException, AuthorizeException, IOException {
|
throws SQLException, AuthorizeException, IOException {
|
||||||
boolean hasPassed = false;
|
// Retrieve all our scores from the metadata & add em up
|
||||||
//Retrieve all our scores from the metadata & add em up
|
int scoreMean = getMeanScore(wfi);
|
||||||
|
//We have passed if we have at least gained our minimum score
|
||||||
|
boolean hasPassed = getMinimumAcceptanceScore() <= scoreMean;
|
||||||
|
//Whether or not we have passed, clear our score information
|
||||||
|
itemService.clearMetadata(c, wfi.getItem(), SCORE_FIELD.schema, SCORE_FIELD.element, SCORE_FIELD.qualifier,
|
||||||
|
Item.ANY);
|
||||||
|
if (hasPassed) {
|
||||||
|
this.addRatingInfoToProv(c, wfi, scoreMean);
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
||||||
|
} else {
|
||||||
|
//We haven't passed, reject our item
|
||||||
|
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
||||||
|
.sendWorkflowItemBackSubmission(c, wfi, c.getCurrentUser(), this.getProvenanceStartId(),
|
||||||
|
"The item was reject due to a bad review score.");
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMeanScore(XmlWorkflowItem wfi) {
|
||||||
List<MetadataValue> scores = itemService
|
List<MetadataValue> scores = itemService
|
||||||
.getMetadata(wfi.getItem(), WorkflowRequirementsService.WORKFLOW_SCHEMA, "score", null, Item.ANY);
|
.getMetadata(wfi.getItem(), SCORE_FIELD.schema, SCORE_FIELD.element, SCORE_FIELD.qualifier, Item.ANY);
|
||||||
|
int scoreMean = 0;
|
||||||
if (0 < scores.size()) {
|
if (0 < scores.size()) {
|
||||||
int totalScoreCount = 0;
|
int totalScoreCount = 0;
|
||||||
for (MetadataValue score : scores) {
|
for (MetadataValue score : scores) {
|
||||||
totalScoreCount += Integer.parseInt(score.getValue());
|
totalScoreCount += Integer.parseInt(score.getValue());
|
||||||
}
|
}
|
||||||
int scoreMean = totalScoreCount / scores.size();
|
scoreMean = totalScoreCount / scores.size();
|
||||||
//We have passed if we have at least gained our minimum score
|
}
|
||||||
hasPassed = getMinimumAcceptanceScore() <= scoreMean;
|
return scoreMean;
|
||||||
//Wether or not we have passed, clear our score information
|
}
|
||||||
itemService
|
|
||||||
.clearMetadata(c, wfi.getItem(), WorkflowRequirementsService.WORKFLOW_SCHEMA, "score", null, Item.ANY);
|
|
||||||
|
|
||||||
String provDescription = getProvenanceStartId() + " Approved for entry into archive with a score of: " +
|
private void addRatingInfoToProv(Context c, XmlWorkflowItem wfi, int scoreMean)
|
||||||
scoreMean;
|
throws SQLException, AuthorizeException {
|
||||||
itemService.addMetadata(c, wfi.getItem(), MetadataSchemaEnum.DC.getName(),
|
StringBuilder provDescription = new StringBuilder();
|
||||||
"description", "provenance", "en", provDescription);
|
provDescription.append(String.format("%s Approved for entry into archive with a score of: %s",
|
||||||
itemService.update(c, wfi.getItem());
|
getProvenanceStartId(), scoreMean));
|
||||||
|
List<MetadataValue> reviews = itemService
|
||||||
|
.getMetadata(wfi.getItem(), REVIEW_FIELD.schema, REVIEW_FIELD.element, REVIEW_FIELD.qualifier, Item.ANY);
|
||||||
|
if (!reviews.isEmpty()) {
|
||||||
|
provDescription.append(" | Reviews: ");
|
||||||
}
|
}
|
||||||
if (hasPassed) {
|
for (MetadataValue review : reviews) {
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
provDescription.append(String.format("; %s", review.getValue()));
|
||||||
} else {
|
|
||||||
//We haven't passed, reject our item
|
|
||||||
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
|
||||||
.sendWorkflowItemBackSubmission(c, wfi, c.getCurrentUser(),
|
|
||||||
this.getProvenanceStartId(),
|
|
||||||
"The item was reject due to a bad review score.");
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
|
||||||
}
|
}
|
||||||
|
c.turnOffAuthorisationSystem();
|
||||||
|
itemService.addMetadata(c, wfi.getItem(), MetadataSchemaEnum.DC.getName(),
|
||||||
|
"description", "provenance", "en", provDescription.toString());
|
||||||
|
itemService.update(c, wfi.getItem());
|
||||||
|
c.restoreAuthSystemState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getOptions() {
|
public List<String> getOptions() {
|
||||||
return new ArrayList<>();
|
List<String> options = new ArrayList<>();
|
||||||
|
options.add(RETURN_TO_POOL);
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMinimumAcceptanceScore() {
|
public int getMinimumAcceptanceScore() {
|
||||||
|
@@ -9,14 +9,20 @@ package org.dspace.xmlworkflow.state.actions.processingaction;
|
|||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.app.util.Util;
|
import org.dspace.app.util.Util;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.content.MetadataFieldName;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.xmlworkflow.service.WorkflowRequirementsService;
|
import org.dspace.xmlworkflow.service.WorkflowRequirementsService;
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
import org.dspace.xmlworkflow.state.Step;
|
||||||
|
import org.dspace.xmlworkflow.state.actions.ActionAdvancedInfo;
|
||||||
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
|
|
||||||
@@ -24,40 +30,121 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
|||||||
* This action will allow multiple users to rate a certain item
|
* This action will allow multiple users to rate a certain item
|
||||||
* if the mean of this score is higher then the minimum score the
|
* if the mean of this score is higher then the minimum score the
|
||||||
* item will be sent to the next action/step else it will be rejected
|
* item will be sent to the next action/step else it will be rejected
|
||||||
*
|
|
||||||
* @author Bram De Schouwer (bram.deschouwer at dot com)
|
|
||||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
|
||||||
* @author Ben Bosman (ben at atmire dot com)
|
|
||||||
* @author Mark Diggory (markd at atmire dot com)
|
|
||||||
*/
|
*/
|
||||||
public class ScoreReviewAction extends ProcessingAction {
|
public class ScoreReviewAction extends ProcessingAction {
|
||||||
|
private static final Logger log = LogManager.getLogger(ScoreReviewAction.class);
|
||||||
|
|
||||||
private static final String SUBMIT_SCORE = "submit_score";
|
// Option(s)
|
||||||
|
public static final String SUBMIT_SCORE = "submit_score";
|
||||||
|
|
||||||
|
// Response param(s)
|
||||||
|
private static final String SCORE = "score";
|
||||||
|
private static final String REVIEW = "review";
|
||||||
|
|
||||||
|
// Metadata fields to save params in
|
||||||
|
public static final MetadataFieldName SCORE_FIELD =
|
||||||
|
new MetadataFieldName(WorkflowRequirementsService.WORKFLOW_SCHEMA, SCORE, null);
|
||||||
|
public static final MetadataFieldName REVIEW_FIELD =
|
||||||
|
new MetadataFieldName(WorkflowRequirementsService.WORKFLOW_SCHEMA, REVIEW, null);
|
||||||
|
|
||||||
|
// Whether or not it is required that a text review is added to the rating
|
||||||
|
private boolean descriptionRequired;
|
||||||
|
// Maximum value rating is allowed to be
|
||||||
|
private int maxValue;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activate(Context c, XmlWorkflowItem wf) {
|
public void activate(Context c, XmlWorkflowItem wf) {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
||||||
throws SQLException, AuthorizeException {
|
throws SQLException, AuthorizeException {
|
||||||
if (request.getParameter(SUBMIT_SCORE) != null) {
|
if (super.isOptionInParam(request) &&
|
||||||
int score = Util.getIntParameter(request, "score");
|
StringUtils.equalsIgnoreCase(Util.getSubmitButton(request, SUBMIT_CANCEL), SUBMIT_SCORE)) {
|
||||||
//Add our score to the metadata
|
return processSetRating(c, wfi, request);
|
||||||
itemService.addMetadata(c, wfi.getItem(), WorkflowRequirementsService.WORKFLOW_SCHEMA, "score", null, null,
|
|
||||||
String.valueOf(score));
|
|
||||||
itemService.update(c, wfi.getItem());
|
|
||||||
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
|
||||||
} else {
|
|
||||||
//We have pressed the leave button so return to our submission page
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
|
||||||
}
|
}
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionResult processSetRating(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
|
||||||
|
int score = Util.getIntParameter(request, SCORE);
|
||||||
|
String review = request.getParameter(REVIEW);
|
||||||
|
if (!this.checkRequestValid(score, review)) {
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_ERROR);
|
||||||
|
}
|
||||||
|
//Add our rating and review to the metadata
|
||||||
|
itemService.addMetadata(c, wfi.getItem(), SCORE_FIELD.schema, SCORE_FIELD.element, SCORE_FIELD.qualifier, null,
|
||||||
|
String.valueOf(score));
|
||||||
|
if (StringUtils.isNotBlank(review)) {
|
||||||
|
itemService.addMetadata(c, wfi.getItem(), REVIEW_FIELD.schema, REVIEW_FIELD.element,
|
||||||
|
REVIEW_FIELD.qualifier, null, String.format("%s - %s", score, review));
|
||||||
|
}
|
||||||
|
itemService.update(c, wfi.getItem());
|
||||||
|
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request is not valid if:
|
||||||
|
* - Given score is higher than configured maxValue
|
||||||
|
* - There is no review given and description is configured to be required
|
||||||
|
* Config in workflow-actions.xml
|
||||||
|
*
|
||||||
|
* @param score Given score rating from request
|
||||||
|
* @param review Given review/description from request
|
||||||
|
* @return True if valid request params with config, otherwise false
|
||||||
|
*/
|
||||||
|
private boolean checkRequestValid(int score, String review) {
|
||||||
|
if (score > this.maxValue) {
|
||||||
|
log.error("{} only allows max rating {} (config workflow-actions.xml), given rating of " +
|
||||||
|
"{} not allowed.", this.getClass().toString(), this.maxValue, score);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(review) && this.descriptionRequired) {
|
||||||
|
log.error("{} has config descriptionRequired=true (workflow-actions.xml), so rating " +
|
||||||
|
"requests without 'review' query param containing description are not allowed",
|
||||||
|
this.getClass().toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getOptions() {
|
public List<String> getOptions() {
|
||||||
|
return List.of(SUBMIT_SCORE, RETURN_TO_POOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getAdvancedOptions() {
|
||||||
return Arrays.asList(SUBMIT_SCORE);
|
return Arrays.asList(SUBMIT_SCORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ActionAdvancedInfo> getAdvancedInfo() {
|
||||||
|
ScoreReviewActionAdvancedInfo scoreReviewActionAdvancedInfo = new ScoreReviewActionAdvancedInfo();
|
||||||
|
scoreReviewActionAdvancedInfo.setDescriptionRequired(descriptionRequired);
|
||||||
|
scoreReviewActionAdvancedInfo.setMaxValue(maxValue);
|
||||||
|
scoreReviewActionAdvancedInfo.setType(SUBMIT_SCORE);
|
||||||
|
scoreReviewActionAdvancedInfo.generateId(SUBMIT_SCORE);
|
||||||
|
return Collections.singletonList(scoreReviewActionAdvancedInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter that sets the descriptionRequired property from workflow-actions.xml
|
||||||
|
* @param descriptionRequired boolean whether a description is required
|
||||||
|
*/
|
||||||
|
public void setDescriptionRequired(boolean descriptionRequired) {
|
||||||
|
this.descriptionRequired = descriptionRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter that sets the maxValue property from workflow-actions.xml
|
||||||
|
* @param maxValue integer of the maximum allowed value
|
||||||
|
*/
|
||||||
|
public void setMaxValue(int maxValue) {
|
||||||
|
this.maxValue = maxValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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.xmlworkflow.state.actions.processingaction;
|
||||||
|
|
||||||
|
import org.dspace.xmlworkflow.state.actions.ActionAdvancedInfo;
|
||||||
|
import org.springframework.util.DigestUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that holds the advanced information needed for the
|
||||||
|
* {@link org.dspace.xmlworkflow.state.actions.processingaction.ScoreReviewAction}
|
||||||
|
* See config {@code workflow-actions.cfg}
|
||||||
|
*/
|
||||||
|
public class ScoreReviewActionAdvancedInfo extends ActionAdvancedInfo {
|
||||||
|
private boolean descriptionRequired;
|
||||||
|
private int maxValue;
|
||||||
|
|
||||||
|
public boolean isDescriptionRequired() {
|
||||||
|
return descriptionRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescriptionRequired(boolean descriptionRequired) {
|
||||||
|
this.descriptionRequired = descriptionRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxValue() {
|
||||||
|
return maxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxValue(int maxValue) {
|
||||||
|
this.maxValue = maxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateId(String type) {
|
||||||
|
String idString = type
|
||||||
|
+ ";descriptionRequired," + descriptionRequired
|
||||||
|
+ ";maxValue," + maxValue;
|
||||||
|
super.id = DigestUtils.md5DigestAsHex(idString.getBytes());
|
||||||
|
}
|
||||||
|
}
|
@@ -9,17 +9,27 @@ package org.dspace.xmlworkflow.state.actions.processingaction;
|
|||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.app.util.Util;
|
import org.dspace.app.util.Util;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.eperson.Group;
|
||||||
import org.dspace.eperson.service.EPersonService;
|
import org.dspace.eperson.service.EPersonService;
|
||||||
|
import org.dspace.eperson.service.GroupService;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.dspace.xmlworkflow.Role;
|
import org.dspace.xmlworkflow.Role;
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
import org.dspace.xmlworkflow.state.Step;
|
||||||
|
import org.dspace.xmlworkflow.state.actions.ActionAdvancedInfo;
|
||||||
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.WorkflowItemRole;
|
import org.dspace.xmlworkflow.storedcomponents.WorkflowItemRole;
|
||||||
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
||||||
@@ -37,13 +47,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
*/
|
*/
|
||||||
public class SelectReviewerAction extends ProcessingAction {
|
public class SelectReviewerAction extends ProcessingAction {
|
||||||
|
|
||||||
public static final int SEARCH_RESULTS_PAGE = 1;
|
private static final Logger log = LogManager.getLogger(SelectReviewerAction.class);
|
||||||
|
|
||||||
public static final int RESULTS_PER_PAGE = 5;
|
|
||||||
|
|
||||||
private static final String SUBMIT_CANCEL = "submit_cancel";
|
private static final String SUBMIT_CANCEL = "submit_cancel";
|
||||||
private static final String SUBMIT_SEARCH = "submit_search";
|
private static final String SUBMIT_SELECT_REVIEWER = "submit_select_reviewer";
|
||||||
private static final String SUBMIT_SELECT_REVIEWER = "submit_select_reviewer_";
|
private static final String PARAM_REVIEWER = "eperson";
|
||||||
|
|
||||||
|
private static final String CONFIG_REVIEWER_GROUP = "action.selectrevieweraction.group";
|
||||||
|
|
||||||
private Role role;
|
private Role role;
|
||||||
|
|
||||||
@@ -53,6 +63,15 @@ public class SelectReviewerAction extends ProcessingAction {
|
|||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
private WorkflowItemRoleService workflowItemRoleService;
|
private WorkflowItemRoleService workflowItemRoleService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GroupService groupService;
|
||||||
|
|
||||||
|
private static Group selectFromReviewsGroup;
|
||||||
|
private static boolean selectFromReviewsGroupInitialised = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activate(Context c, XmlWorkflowItem wf) {
|
public void activate(Context c, XmlWorkflowItem wf) {
|
||||||
|
|
||||||
@@ -60,56 +79,128 @@ public class SelectReviewerAction extends ProcessingAction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
||||||
throws SQLException, AuthorizeException {
|
throws SQLException, AuthorizeException {
|
||||||
String submitButton = Util.getSubmitButton(request, SUBMIT_CANCEL);
|
String submitButton = Util.getSubmitButton(request, SUBMIT_CANCEL);
|
||||||
|
|
||||||
//Check if our user has pressed cancel
|
//Check if our user has pressed cancel
|
||||||
if (submitButton.equals(SUBMIT_CANCEL)) {
|
if (submitButton.equals(SUBMIT_CANCEL)) {
|
||||||
//Send us back to the submissions page
|
//Send us back to the submissions page
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
|
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
|
||||||
|
|
||||||
} else if (submitButton.equals(SUBMIT_SEARCH)) {
|
|
||||||
//Perform the search
|
|
||||||
String query = request.getParameter("query");
|
|
||||||
int page = Util.getIntParameter(request, "result-page");
|
|
||||||
if (page == -1) {
|
|
||||||
page = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int resultCount = ePersonService.searchResultCount(c, query);
|
|
||||||
List<EPerson> epeople = ePersonService.search(c, query, page * RESULTS_PER_PAGE, RESULTS_PER_PAGE);
|
|
||||||
|
|
||||||
|
|
||||||
request.setAttribute("eperson-result-count", resultCount);
|
|
||||||
request.setAttribute("eperson-results", epeople);
|
|
||||||
request.setAttribute("result-page", page);
|
|
||||||
request.setAttribute("page", SEARCH_RESULTS_PAGE);
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_PAGE, SEARCH_RESULTS_PAGE);
|
|
||||||
} else if (submitButton.startsWith(SUBMIT_SELECT_REVIEWER)) {
|
} else if (submitButton.startsWith(SUBMIT_SELECT_REVIEWER)) {
|
||||||
//Retrieve the identifier of the eperson which will do the reviewing
|
return processSelectReviewers(c, wfi, request);
|
||||||
UUID reviewerId = UUID.fromString(submitButton.substring(submitButton.lastIndexOf("_") + 1));
|
|
||||||
EPerson reviewer = ePersonService.find(c, reviewerId);
|
|
||||||
//Assign the reviewer. The workflowitemrole will be translated into a task in the autoassign
|
|
||||||
WorkflowItemRole workflowItemRole = workflowItemRoleService.create(c);
|
|
||||||
workflowItemRole.setEPerson(reviewer);
|
|
||||||
workflowItemRole.setRoleId(getRole().getId());
|
|
||||||
workflowItemRole.setWorkflowItem(wfi);
|
|
||||||
workflowItemRoleService.update(c, workflowItemRole);
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//There are only 2 active buttons on this page, so if anything else happens just return an error
|
//There are only 2 active buttons on this page, so if anything else happens just return an error
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_ERROR);
|
return new ActionResult(ActionResult.TYPE.TYPE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to handle the {@link this#SUBMIT_SELECT_REVIEWER} action:
|
||||||
|
* - will retrieve the reviewer(s) uuid from request (param {@link this#PARAM_REVIEWER})
|
||||||
|
* - assign them to a {@link WorkflowItemRole}
|
||||||
|
* - In {@link org.dspace.xmlworkflow.state.actions.userassignment.AutoAssignAction} these reviewer(s) will get
|
||||||
|
* claimed task for this {@link XmlWorkflowItem}
|
||||||
|
* Will result in error if:
|
||||||
|
* - No reviewer(s) uuid in request (param {@link this#PARAM_REVIEWER})
|
||||||
|
* - If none of the reviewer(s) uuid passed along result in valid EPerson
|
||||||
|
* - If the reviewer(s) passed along are not in {@link this#selectFromReviewsGroup} when it is set
|
||||||
|
*
|
||||||
|
* @param c current DSpace session
|
||||||
|
* @param wfi the item on which the action is to be performed
|
||||||
|
* @param request the current client request
|
||||||
|
* @return the result of performing the action
|
||||||
|
*/
|
||||||
|
private ActionResult processSelectReviewers(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
//Retrieve the identifier of the eperson which will do the reviewing
|
||||||
|
String[] reviewerIds = request.getParameterValues(PARAM_REVIEWER);
|
||||||
|
if (ArrayUtils.isEmpty(reviewerIds)) {
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_ERROR);
|
||||||
|
}
|
||||||
|
List<EPerson> reviewers = new ArrayList<>();
|
||||||
|
for (String reviewerId : reviewerIds) {
|
||||||
|
EPerson reviewer = ePersonService.find(c, UUID.fromString(reviewerId));
|
||||||
|
if (reviewer == null) {
|
||||||
|
log.warn("No EPerson found with uuid {}", reviewerId);
|
||||||
|
} else {
|
||||||
|
reviewers.add(reviewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.checkReviewersValid(c, reviewers)) {
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
createWorkflowItemRole(c, wfi, reviewers);
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkReviewersValid(Context c, List<EPerson> reviewers) throws SQLException {
|
||||||
|
if (reviewers.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Group group = this.getGroup(c);
|
||||||
|
if (group != null) {
|
||||||
|
for (EPerson reviewer: reviewers) {
|
||||||
|
if (!groupService.isMember(c, reviewer, group)) {
|
||||||
|
log.error("Reviewers selected must be member of group {}", group.getID());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorkflowItemRole createWorkflowItemRole(Context c, XmlWorkflowItem wfi, List<EPerson> reviewers)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
WorkflowItemRole workflowItemRole = workflowItemRoleService.create(c);
|
||||||
|
workflowItemRole.setRoleId(getRole().getId());
|
||||||
|
workflowItemRole.setWorkflowItem(wfi);
|
||||||
|
if (reviewers.size() == 1) {
|
||||||
|
// 1 reviewer in workflowitemrole => will be translated into a claimed task in the autoassign
|
||||||
|
workflowItemRole.setEPerson(reviewers.get(0));
|
||||||
|
} else {
|
||||||
|
// multiple reviewers, create a temporary group and assign this group, the workflowitemrole will be
|
||||||
|
// translated into a claimed task for reviewers in the autoassign, where group will be deleted
|
||||||
|
c.turnOffAuthorisationSystem();
|
||||||
|
Group selectedReviewsGroup = groupService.create(c);
|
||||||
|
groupService.setName(selectedReviewsGroup, "selectedReviewsGroup_" + wfi.getID());
|
||||||
|
for (EPerson reviewer : reviewers) {
|
||||||
|
groupService.addMember(c, selectedReviewsGroup, reviewer);
|
||||||
|
}
|
||||||
|
workflowItemRole.setGroup(selectedReviewsGroup);
|
||||||
|
c.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
workflowItemRoleService.update(c, workflowItemRole);
|
||||||
|
return workflowItemRole;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getOptions() {
|
public List<String> getOptions() {
|
||||||
List<String> options = new ArrayList<>();
|
List<String> options = new ArrayList<>();
|
||||||
options.add(SUBMIT_SEARCH);
|
|
||||||
options.add(SUBMIT_SELECT_REVIEWER);
|
options.add(SUBMIT_SELECT_REVIEWER);
|
||||||
|
options.add(RETURN_TO_POOL);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getAdvancedOptions() {
|
||||||
|
return Arrays.asList(SUBMIT_SELECT_REVIEWER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ActionAdvancedInfo> getAdvancedInfo() {
|
||||||
|
List<ActionAdvancedInfo> advancedInfo = new ArrayList<>();
|
||||||
|
SelectReviewerActionAdvancedInfo selectReviewerActionAdvancedInfo = new SelectReviewerActionAdvancedInfo();
|
||||||
|
if (getGroup(null) != null) {
|
||||||
|
selectReviewerActionAdvancedInfo.setGroup(getGroup(null).getID().toString());
|
||||||
|
}
|
||||||
|
selectReviewerActionAdvancedInfo.setType(SUBMIT_SELECT_REVIEWER);
|
||||||
|
selectReviewerActionAdvancedInfo.generateId(SUBMIT_SELECT_REVIEWER);
|
||||||
|
advancedInfo.add(selectReviewerActionAdvancedInfo);
|
||||||
|
return advancedInfo;
|
||||||
|
}
|
||||||
|
|
||||||
public Role getRole() {
|
public Role getRole() {
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
@@ -118,4 +209,49 @@ public class SelectReviewerAction extends ProcessingAction {
|
|||||||
public void setRole(Role role) {
|
public void setRole(Role role) {
|
||||||
this.role = role;
|
this.role = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Reviewer group from the "action.selectrevieweraction.group" property in actions.cfg by its UUID or name
|
||||||
|
* Returns null if no (valid) group configured
|
||||||
|
*
|
||||||
|
* @return configured reviewers Group from property or null if none
|
||||||
|
*/
|
||||||
|
private Group getGroup(@Nullable Context context) {
|
||||||
|
if (selectFromReviewsGroupInitialised) {
|
||||||
|
return this.selectFromReviewsGroup;
|
||||||
|
}
|
||||||
|
if (context == null) {
|
||||||
|
context = new Context();
|
||||||
|
}
|
||||||
|
String groupIdOrName = configurationService.getProperty(CONFIG_REVIEWER_GROUP);
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(groupIdOrName)) {
|
||||||
|
Group group = null;
|
||||||
|
try {
|
||||||
|
// try to get group by name
|
||||||
|
group = groupService.findByName(context, groupIdOrName);
|
||||||
|
if (group == null) {
|
||||||
|
// try to get group by uuid if not a name
|
||||||
|
group = groupService.find(context, UUID.fromString(groupIdOrName));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// There is an issue with the reviewer group that is set; if it is not set then can be chosen
|
||||||
|
// from all epeople
|
||||||
|
log.error("Issue with determining matching group for config {}={} for reviewer group of " +
|
||||||
|
"select reviewers workflow", CONFIG_REVIEWER_GROUP, groupIdOrName);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectFromReviewsGroup = group;
|
||||||
|
}
|
||||||
|
selectFromReviewsGroupInitialised = true;
|
||||||
|
return this.selectFromReviewsGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be used by IT, e.g. {@code XmlWorkflowServiceIT}, when defining new 'Reviewers' group
|
||||||
|
*/
|
||||||
|
static public void resetGroup() {
|
||||||
|
selectFromReviewsGroup = null;
|
||||||
|
selectFromReviewsGroupInitialised = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* 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.xmlworkflow.state.actions.processingaction;
|
||||||
|
|
||||||
|
import org.dspace.xmlworkflow.state.actions.ActionAdvancedInfo;
|
||||||
|
import org.springframework.util.DigestUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that holds the advanced information needed for the
|
||||||
|
* {@link org.dspace.xmlworkflow.state.actions.processingaction.SelectReviewerAction}
|
||||||
|
* See config {@code workflow-actions.cfg}
|
||||||
|
*/
|
||||||
|
public class SelectReviewerActionAdvancedInfo extends ActionAdvancedInfo {
|
||||||
|
private String group;
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(String group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateId(String type) {
|
||||||
|
String idString = type
|
||||||
|
+ ";group," + group;
|
||||||
|
super.id = DigestUtils.md5DigestAsHex(idString.getBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -13,11 +13,15 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.app.util.Util;
|
import org.dspace.app.util.Util;
|
||||||
import org.dspace.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.DCDate;
|
import org.dspace.content.WorkspaceItem;
|
||||||
import org.dspace.content.MetadataSchemaEnum;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.workflow.WorkflowException;
|
||||||
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
|
||||||
import org.dspace.xmlworkflow.state.Step;
|
import org.dspace.xmlworkflow.state.Step;
|
||||||
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
import org.dspace.xmlworkflow.state.actions.ActionResult;
|
||||||
@@ -34,39 +38,59 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
|
|||||||
* @author Mark Diggory (markd at atmire dot com)
|
* @author Mark Diggory (markd at atmire dot com)
|
||||||
*/
|
*/
|
||||||
public class SingleUserReviewAction extends ProcessingAction {
|
public class SingleUserReviewAction extends ProcessingAction {
|
||||||
|
private static final Logger log = LogManager.getLogger(SingleUserReviewAction.class);
|
||||||
public static final int MAIN_PAGE = 0;
|
|
||||||
public static final int REJECT_PAGE = 1;
|
|
||||||
public static final int SUBMITTER_IS_DELETED_PAGE = 2;
|
|
||||||
|
|
||||||
public static final int OUTCOME_REJECT = 1;
|
public static final int OUTCOME_REJECT = 1;
|
||||||
|
|
||||||
protected static final String SUBMIT_APPROVE = "submit_approve";
|
|
||||||
protected static final String SUBMIT_REJECT = "submit_reject";
|
|
||||||
protected static final String SUBMIT_DECLINE_TASK = "submit_decline_task";
|
protected static final String SUBMIT_DECLINE_TASK = "submit_decline_task";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activate(Context c, XmlWorkflowItem wfItem) {
|
public void activate(Context c, XmlWorkflowItem wfItem) {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
public ActionResult execute(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
||||||
throws SQLException, AuthorizeException, IOException {
|
throws SQLException, AuthorizeException, IOException, WorkflowException {
|
||||||
int page = Util.getIntParameter(request, "page");
|
if (!super.isOptionInParam(request)) {
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
|
||||||
switch (page) {
|
}
|
||||||
case MAIN_PAGE:
|
switch (Util.getSubmitButton(request, SUBMIT_CANCEL)) {
|
||||||
return processMainPage(c, wfi, step, request);
|
case SUBMIT_APPROVE:
|
||||||
case REJECT_PAGE:
|
return processAccept(c, wfi);
|
||||||
return processRejectPage(c, wfi, step, request);
|
case SUBMIT_REJECT:
|
||||||
case SUBMITTER_IS_DELETED_PAGE:
|
return processReject(c, wfi, request);
|
||||||
return processSubmitterIsDeletedPage(c, wfi, request);
|
case SUBMIT_DECLINE_TASK:
|
||||||
|
return processDecline(c, wfi);
|
||||||
default:
|
default:
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
|
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process {@link super#SUBMIT_REJECT} on this action, will either:
|
||||||
|
* - If submitter of item no longer exists => Permanently delete corresponding item (no wfi/wsi remaining)
|
||||||
|
* - Otherwise: reject item back to submission => becomes wsi of submitter again
|
||||||
|
*/
|
||||||
|
private ActionResult processReject(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
||||||
|
throws SQLException, IOException, AuthorizeException {
|
||||||
|
if (wfi.getSubmitter() == null) {
|
||||||
|
// If the original submitter is no longer there, delete the task
|
||||||
|
return processDelete(c, wfi);
|
||||||
|
} else {
|
||||||
|
return super.processRejectPage(c, wfi, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept the workflow item => last step in workflow so will be archived
|
||||||
|
* Info on step & reviewer will be added on metadata dc.description.provenance of resulting item
|
||||||
|
*/
|
||||||
|
public ActionResult processAccept(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
|
||||||
|
super.addApprovedProvenance(c, wfi);
|
||||||
|
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getOptions() {
|
public List<String> getOptions() {
|
||||||
List<String> options = new ArrayList<>();
|
List<String> options = new ArrayList<>();
|
||||||
@@ -76,87 +100,29 @@ public class SingleUserReviewAction extends ProcessingAction {
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult processMainPage(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
/**
|
||||||
throws SQLException, AuthorizeException {
|
* Since original submitter no longer exists, workflow item is permanently deleted
|
||||||
if (request.getParameter(SUBMIT_APPROVE) != null) {
|
*/
|
||||||
//Delete the tasks
|
private ActionResult processDelete(Context c, XmlWorkflowItem wfi)
|
||||||
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
|
|
||||||
if (wfi.getSubmitter() == null) {
|
|
||||||
request.setAttribute("page", SUBMITTER_IS_DELETED_PAGE);
|
|
||||||
} else {
|
|
||||||
request.setAttribute("page", REJECT_PAGE);
|
|
||||||
}
|
|
||||||
// We have pressed reject item, so take the user to a page where they can reject
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
|
|
||||||
} else if (request.getParameter(SUBMIT_DECLINE_TASK) != null) {
|
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, OUTCOME_REJECT);
|
|
||||||
|
|
||||||
} 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 {
|
|
||||||
//Add the provenance for the accept
|
|
||||||
String now = DCDate.getCurrent().toString();
|
|
||||||
|
|
||||||
// Get user's name + email address
|
|
||||||
String usersName = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
|
||||||
.getEPersonName(c.getCurrentUser());
|
|
||||||
|
|
||||||
String provDescription = getProvenanceStartId() + " Approved for entry into archive by "
|
|
||||||
+ usersName + " on " + now + " (GMT) ";
|
|
||||||
|
|
||||||
// Add to item as a DC field
|
|
||||||
itemService.addMetadata(c, wfi.getItem(), MetadataSchemaEnum.DC.getName(), "description", "provenance", "en",
|
|
||||||
provDescription);
|
|
||||||
itemService.update(c, wfi.getItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionResult processRejectPage(Context c, XmlWorkflowItem wfi, Step step, HttpServletRequest request)
|
|
||||||
throws SQLException, AuthorizeException, IOException {
|
throws SQLException, AuthorizeException, IOException {
|
||||||
if (request.getParameter("submit_reject") != null) {
|
EPerson user = c.getCurrentUser();
|
||||||
String reason = request.getParameter("reason");
|
c.turnOffAuthorisationSystem();
|
||||||
if (reason == null || 0 == reason.trim().length()) {
|
WorkspaceItem workspaceItem = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
||||||
request.setAttribute("page", REJECT_PAGE);
|
.abort(c, wfi, user);
|
||||||
addErrorField(request, "reason");
|
ContentServiceFactory.getInstance().getWorkspaceItemService().deleteAll(c, workspaceItem);
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_ERROR);
|
c.restoreAuthSystemState();
|
||||||
}
|
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
||||||
|
|
||||||
//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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult processSubmitterIsDeletedPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
|
/**
|
||||||
throws SQLException, AuthorizeException, IOException {
|
* Selected reviewer declines to review task, then the workflow is aborted and restarted
|
||||||
if (request.getParameter("submit_delete") != null) {
|
*/
|
||||||
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
private ActionResult processDecline(Context c, XmlWorkflowItem wfi)
|
||||||
.deleteWorkflowByWorkflowItem(c, wfi, c.getCurrentUser());
|
throws SQLException, IOException, AuthorizeException, WorkflowException {
|
||||||
// Delete and send user back to myDspace page
|
c.turnOffAuthorisationSystem();
|
||||||
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
xmlWorkflowService.restartWorkflow(c, wfi, c.getCurrentUser(), this.getProvenanceStartId());
|
||||||
} else if (request.getParameter("submit_keep_it") != null) {
|
c.restoreAuthSystemState();
|
||||||
// Do nothing, just send it back to myDspace page
|
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -80,6 +80,10 @@ public class AutoAssignAction extends UserSelectionAction {
|
|||||||
}
|
}
|
||||||
//Delete our workflow item role since the users have been assigned
|
//Delete our workflow item role since the users have been assigned
|
||||||
workflowItemRoleService.delete(c, workflowItemRole);
|
workflowItemRoleService.delete(c, workflowItemRole);
|
||||||
|
if (role.isDeleteTemporaryGroup() && workflowItemRole.getGroup() != null) {
|
||||||
|
// Delete temporary groups created after members have workflow task assigned
|
||||||
|
groupService.delete(c, workflowItemRole.getGroup());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn(LogHelper.getHeader(c, "Error while executing auto assign action",
|
log.warn(LogHelper.getHeader(c, "Error while executing auto assign action",
|
||||||
@@ -127,7 +131,7 @@ public class AutoAssignAction extends UserSelectionAction {
|
|||||||
protected void createTaskForEPerson(Context c, XmlWorkflowItem wfi, Step step, WorkflowActionConfig actionConfig,
|
protected void createTaskForEPerson(Context c, XmlWorkflowItem wfi, Step step, WorkflowActionConfig actionConfig,
|
||||||
EPerson user) throws SQLException, AuthorizeException, IOException {
|
EPerson user) throws SQLException, AuthorizeException, IOException {
|
||||||
if (claimedTaskService.find(c, wfi, step.getId(), actionConfig.getId()) != null) {
|
if (claimedTaskService.find(c, wfi, step.getId(), actionConfig.getId()) != null) {
|
||||||
workflowRequirementsService.addClaimedUser(c, wfi, step, c.getCurrentUser());
|
workflowRequirementsService.addClaimedUser(c, wfi, step, user);
|
||||||
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
|
||||||
.createOwnedTask(c, wfi, step, actionConfig, user);
|
.createOwnedTask(c, wfi, step, actionConfig, user);
|
||||||
}
|
}
|
||||||
|
@@ -138,6 +138,10 @@ public class ClaimAction extends UserSelectionAction {
|
|||||||
RoleMembers roleMembers = role.getMembers(context, wfi);
|
RoleMembers roleMembers = role.getMembers(context, wfi);
|
||||||
|
|
||||||
ArrayList<EPerson> epersons = roleMembers.getAllUniqueMembers(context);
|
ArrayList<EPerson> epersons = roleMembers.getAllUniqueMembers(context);
|
||||||
|
if (epersons.isEmpty() || step.getRequiredUsers() > epersons.size()) {
|
||||||
|
log.warn(String.format("There must be at least %s ePerson(s) in the group",
|
||||||
|
step.getRequiredUsers()));
|
||||||
|
}
|
||||||
return !(epersons.isEmpty() || step.getRequiredUsers() > epersons.size());
|
return !(epersons.isEmpty() || step.getRequiredUsers() > epersons.size());
|
||||||
} else {
|
} else {
|
||||||
// We don't have a role and do have a UI so throw a workflow exception
|
// We don't have a role and do have a UI so throw a workflow exception
|
||||||
|
@@ -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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
-- ADD table subscription_parameter
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
CREATE SEQUENCE if NOT EXISTS subscription_parameter_seq;
|
||||||
|
-------------------------------------------------------
|
||||||
|
-- Create the subscription_parameter table
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE TABLE if NOT EXISTS subscription_parameter
|
||||||
|
(
|
||||||
|
subscription_parameter_id INTEGER NOT NULL,
|
||||||
|
name CHARACTER VARYING(255),
|
||||||
|
value CHARACTER VARYING(255),
|
||||||
|
subscription_id INTEGER NOT NULL,
|
||||||
|
CONSTRAINT subscription_parameter_pkey PRIMARY KEY (subscription_parameter_id),
|
||||||
|
CONSTRAINT subscription_parameter_subscription_fkey FOREIGN KEY (subscription_id) REFERENCES subscription (subscription_id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription ADD COLUMN if NOT EXISTS dspace_object_id UUID;
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription ADD COLUMN if NOT EXISTS type CHARACTER VARYING(255);
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription DROP CONSTRAINT IF EXISTS subscription_dspaceobject_fkey;
|
||||||
|
ALTER TABLE subscription ADD CONSTRAINT subscription_dspaceobject_fkey FOREIGN KEY (dspace_object_id) REFERENCES dspaceobject (uuid);
|
||||||
|
-- --
|
||||||
|
UPDATE subscription set dspace_object_id = collection_id , type = 'content';
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription DROP CONSTRAINT IF EXISTS Subscription_collection_id_fk;
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription DROP COLUMN IF EXISTS collection_id;
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -0,0 +1,22 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
-- Create table for System wide alerts
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE SEQUENCE alert_id_seq;
|
||||||
|
|
||||||
|
CREATE TABLE systemwidealert
|
||||||
|
(
|
||||||
|
alert_id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
message VARCHAR(512),
|
||||||
|
allow_sessions VARCHAR(64),
|
||||||
|
countdown_to TIMESTAMP,
|
||||||
|
active BOOLEAN
|
||||||
|
);
|
@@ -0,0 +1,45 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
-- ADD table subscription_parameter
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
CREATE SEQUENCE if NOT EXISTS subscription_parameter_seq;
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
-- ADD table subscription_parameter
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
CREATE TABLE if NOT EXISTS subscription_parameter
|
||||||
|
(
|
||||||
|
subscription_parameter_id INTEGER NOT NULL,
|
||||||
|
name VARCHAR(255),
|
||||||
|
value VARCHAR(255),
|
||||||
|
subscription_id INTEGER NOT NULL,
|
||||||
|
CONSTRAINT subscription_parameter_pkey PRIMARY KEY (subscription_parameter_id),
|
||||||
|
CONSTRAINT subscription_parameter_subscription_fkey FOREIGN KEY (subscription_id)
|
||||||
|
REFERENCES subscription (subscription_id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
-- --
|
||||||
|
|
||||||
|
ALTER TABLE subscription ADD COLUMN if NOT EXISTS dspace_object_id UUID;
|
||||||
|
---- --
|
||||||
|
ALTER TABLE subscription ADD COLUMN if NOT EXISTS type CHARACTER VARYING(255);
|
||||||
|
--
|
||||||
|
UPDATE subscription SET dspace_object_id = collection_id , type = 'content';
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription DROP CONSTRAINT IF EXISTS subscription_dspaceobject_fkey;
|
||||||
|
ALTER TABLE subscription ADD CONSTRAINT subscription_dspaceobject_fkey FOREIGN KEY (dspace_object_id) REFERENCES dspaceobject (uuid);
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription DROP CONSTRAINT IF EXISTS subscription_collection_id_fkey;
|
||||||
|
---- --
|
||||||
|
ALTER TABLE subscription DROP COLUMN IF EXISTS collection_id;
|
||||||
|
-- --
|
||||||
|
INSERT INTO subscription_parameter (subscription_parameter_id, name, value, subscription_id)
|
||||||
|
SELECT getnextid('subscription_parameter'), 'frequency', 'D', subscription_id from "subscription" ;
|
||||||
|
|
@@ -0,0 +1,22 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
-- Create table for System wide alerts
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE SEQUENCE alert_id_seq;
|
||||||
|
|
||||||
|
CREATE TABLE systemwidealert
|
||||||
|
(
|
||||||
|
alert_id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
message VARCHAR(512),
|
||||||
|
allow_sessions VARCHAR(64),
|
||||||
|
countdown_to TIMESTAMP,
|
||||||
|
active BOOLEAN
|
||||||
|
);
|
@@ -0,0 +1,43 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
-- ADD table subscription_parameter
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
CREATE SEQUENCE if NOT EXISTS subscription_parameter_seq;
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
-- ADD table subscription_parameter
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
CREATE TABLE if NOT EXISTS subscription_parameter
|
||||||
|
(
|
||||||
|
subscription_parameter_id INTEGER NOT NULL,
|
||||||
|
name CHARACTER VARYING(255),
|
||||||
|
value CHARACTER VARYING(255),
|
||||||
|
subscription_id INTEGER NOT NULL,
|
||||||
|
CONSTRAINT subscription_parameter_pkey PRIMARY KEY (subscription_parameter_id),
|
||||||
|
CONSTRAINT subscription_parameter_subscription_fkey FOREIGN KEY (subscription_id) REFERENCES subscription (subscription_id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription ADD COLUMN if NOT EXISTS dspace_object_id UUID;
|
||||||
|
-- --
|
||||||
|
ALTER TABLE subscription ADD COLUMN if NOT EXISTS type CHARACTER VARYING(255);
|
||||||
|
---- --
|
||||||
|
ALTER TABLE subscription DROP CONSTRAINT IF EXISTS subscription_dspaceobject_fkey;
|
||||||
|
ALTER TABLE subscription ADD CONSTRAINT subscription_dspaceobject_fkey FOREIGN KEY (dspace_object_id) REFERENCES dspaceobject (uuid);
|
||||||
|
--
|
||||||
|
UPDATE subscription SET dspace_object_id = collection_id , type = 'content';
|
||||||
|
--
|
||||||
|
ALTER TABLE subscription DROP CONSTRAINT IF EXISTS subscription_collection_id_fkey;
|
||||||
|
-- --
|
||||||
|
ALTER TABLE subscription DROP COLUMN IF EXISTS collection_id;
|
||||||
|
-- --
|
||||||
|
INSERT INTO subscription_parameter (subscription_parameter_id, name, value, subscription_id)
|
||||||
|
SELECT getnextid('subscription_parameter'), 'frequency', 'D', subscription_id from "subscription" ;
|
||||||
|
|
@@ -0,0 +1,22 @@
|
|||||||
|
--
|
||||||
|
-- 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/
|
||||||
|
--
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
-- Create table for System wide alerts
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE SEQUENCE alert_id_seq;
|
||||||
|
|
||||||
|
CREATE TABLE systemwidealert
|
||||||
|
(
|
||||||
|
alert_id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
message VARCHAR(512),
|
||||||
|
allow_sessions VARCHAR(64),
|
||||||
|
countdown_to TIMESTAMP,
|
||||||
|
active BOOLEAN
|
||||||
|
);
|
@@ -143,6 +143,12 @@
|
|||||||
<processing-class>org.dspace.app.rest.submit.step.SherpaPolicyStep</processing-class>
|
<processing-class>org.dspace.app.rest.submit.step.SherpaPolicyStep</processing-class>
|
||||||
<type>sherpaPolicy</type>
|
<type>sherpaPolicy</type>
|
||||||
</step-definition>
|
</step-definition>
|
||||||
|
|
||||||
|
<step-definition id="identifiers">
|
||||||
|
<heading>submit.progressbar.identifiers</heading>
|
||||||
|
<processing-class>org.dspace.app.rest.submit.step.ShowIdentifiersStep</processing-class>
|
||||||
|
<type>identifiers</type>
|
||||||
|
</step-definition>
|
||||||
</step-definitions>
|
</step-definitions>
|
||||||
|
|
||||||
<!-- The submission-definitions map lays out the detailed definition of -->
|
<!-- The submission-definitions map lays out the detailed definition of -->
|
||||||
@@ -169,6 +175,8 @@
|
|||||||
|
|
||||||
<step id="collection"/>
|
<step id="collection"/>
|
||||||
|
|
||||||
|
<step id="identifiers"/>
|
||||||
|
|
||||||
<!--Step will be to Describe the item. -->
|
<!--Step will be to Describe the item. -->
|
||||||
<step id="traditionalpageone"/>
|
<step id="traditionalpageone"/>
|
||||||
<step id="traditionalpagetwo"/>
|
<step id="traditionalpagetwo"/>
|
||||||
|
@@ -43,7 +43,7 @@ dspace.server.url = http://localhost
|
|||||||
db.driver = org.h2.Driver
|
db.driver = org.h2.Driver
|
||||||
db.dialect=org.hibernate.dialect.H2Dialect
|
db.dialect=org.hibernate.dialect.H2Dialect
|
||||||
# Use a 10 second database lock timeout to avoid occasional JDBC lock timeout errors
|
# Use a 10 second database lock timeout to avoid occasional JDBC lock timeout errors
|
||||||
db.url = jdbc:h2:mem:test;LOCK_TIMEOUT=10000;
|
db.url = jdbc:h2:mem:test;LOCK_TIMEOUT=10000;NON_KEYWORDS=VALUE
|
||||||
db.username = sa
|
db.username = sa
|
||||||
db.password =
|
db.password =
|
||||||
# H2's default schema is PUBLIC
|
# H2's default schema is PUBLIC
|
||||||
|
@@ -0,0 +1,49 @@
|
|||||||
|
#----------------------------------------------------------------------#
|
||||||
|
#---------------------IDENTIFIER CONFIGURATIONS------------------------#
|
||||||
|
#----------------------------------------------------------------------#
|
||||||
|
# These configs are used for additional identifier configuration such #
|
||||||
|
# as the Show Identifiers step which can "pre-mint" DOIs and Handles #
|
||||||
|
#----------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Should configured identifiers (eg handle and DOI) be minted for (future) registration at workspace item creation?
|
||||||
|
# A handle created at this stage will act just like a regular handle created at archive time.
|
||||||
|
# A DOI created at this stage will be in a 'PENDING' status while in workspace and workflow.
|
||||||
|
# At the time of item install, the DOI filter (if any) will be applied and if the item matches the filter, the DOI
|
||||||
|
# status will be updated to TO_BE_REGISTERED. An administrator can also manually progress the DOI status, overriding
|
||||||
|
# any filters, in the item status page.
|
||||||
|
# This option doesn't require the Show Identifiers submission step to be visible.
|
||||||
|
# Default: false
|
||||||
|
identifiers.submission.register = false
|
||||||
|
|
||||||
|
# This configuration property can be set to a filter name to determine if a PENDING DOI for an item
|
||||||
|
# should be queued for registration. If the filter doesn't match, the DOI will stay in PENDING or MINTED status
|
||||||
|
# so that the identifier itself persists in case it is considered for registration in the future.
|
||||||
|
# See doi-filter and other example filters in item-filters.xml.
|
||||||
|
# Default (always_true_filter)
|
||||||
|
identifiers.submission.filter.install = doi_filter
|
||||||
|
|
||||||
|
# This optional configuration property can be set to a filter name, in case there are some initial rules to apply
|
||||||
|
# when first deciding whether a DOI should be be created for a new workspace item with a PENDING status.
|
||||||
|
# This filter is only applied if identifiers.submission.register is true.
|
||||||
|
# This filter is updated as submission data is saved.
|
||||||
|
# Default: (always_true_filter)
|
||||||
|
identifiers.submission.filter.workspace = doi_filter
|
||||||
|
|
||||||
|
# If true, the workspace filter will be applied as submission data is saved. If the filter no longer
|
||||||
|
# matches the item, the DOI will be shifted into a MINTED status and not displayed in the submission section.
|
||||||
|
# If false, then once a DOI has been created with PENDING status it will remain that way until final item install
|
||||||
|
# Default: true
|
||||||
|
#identifiers.submission.strip_pending_during_submission = true
|
||||||
|
|
||||||
|
# This configuration property can be set to a filter name to determine if an item processed by RegisterDOI curation
|
||||||
|
# task should be eligible for a DOI
|
||||||
|
identifiers.submission.filter.curation = always_true_filter
|
||||||
|
|
||||||
|
# Show Register DOI button in item status page?
|
||||||
|
# Default: false
|
||||||
|
identifiers.item-status.register-doi = true
|
||||||
|
|
||||||
|
# Which identifier types to show in submission step?
|
||||||
|
# Default: handle, doi (currently the only supported identifier 'types')
|
||||||
|
identifiers.submission.display = handle
|
||||||
|
identifiers.submission.display = doi
|
@@ -0,0 +1,370 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
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/
|
||||||
|
|
||||||
|
-->
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xmlns:util="http://www.springframework.org/schema/util"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
|
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||||
|
http://www.springframework.org/schema/context
|
||||||
|
http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
|
||||||
|
>
|
||||||
|
<!-- default-autowire-candidates="*Service,*DAO,javax.sql.DataSource"> -->
|
||||||
|
|
||||||
|
<context:annotation-config /> <!-- allows us to use spring annotations in beans -->
|
||||||
|
<bean id="always_true_filter" scope="singleton" class="org.dspace.content.logic.TrueFilter"/>
|
||||||
|
|
||||||
|
<!-- DEFINE CONDITIONS
|
||||||
|
Define condition beans below for use as sub-statements in operator and filter beans
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The MetadataValueMatchCondition takes a regular expression, not an exact value.
|
||||||
|
For an exact value match (rather than 'contains'), make sure to anchor the string
|
||||||
|
like "^Exact Match$".
|
||||||
|
Special characters used in Java regular expressions will need escaping.
|
||||||
|
The below condition returns true if dc.title contains "demo" (case insensitive)
|
||||||
|
-->
|
||||||
|
<bean id="title-contains-demo_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.title" />
|
||||||
|
<entry key="pattern" value="(?i)demo" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
<bean id="item-is-public_condition"
|
||||||
|
class="org.dspace.content.logic.condition.ReadableByGroupCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="group" value="Anonymous" />
|
||||||
|
<entry key="action" value="READ" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- dc.title starts with Pattern -->
|
||||||
|
<bean id="title-starts-with-pattern_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.title" />
|
||||||
|
<entry key="pattern" value="^Pattern" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- dc.type is exactly Journal Article -->
|
||||||
|
<bean id="type-equals-journal-article_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.type" />
|
||||||
|
<entry key="pattern" value="^Journal Article$" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- dc.type is exactly Dataset -->
|
||||||
|
<bean id="type-equals-dataset_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.type" />
|
||||||
|
<entry key="pattern" value="^Dataset$" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
A filter that checks if any value of dc.identifier.uri contains "10.12345/".
|
||||||
|
-->
|
||||||
|
<bean id="dc-identifier-uri-contains-doi_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.identifier.uri" />
|
||||||
|
<entry key="pattern" value="10.12345/" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- dc.type ends with any of the listed values, as per XOAI "driverDocumentTypeCondition" -->
|
||||||
|
<bean id="driver-document-type_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValuesMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.type" />
|
||||||
|
<entry key="patterns">
|
||||||
|
<list>
|
||||||
|
<value>article$</value>
|
||||||
|
<value>bachelorThesis$</value>
|
||||||
|
<value>masterThesis$</value>
|
||||||
|
<value>doctoralThesis$</value>
|
||||||
|
<value>book$</value>
|
||||||
|
<value>bookPart$</value>
|
||||||
|
<value>review$</value>
|
||||||
|
<value>conferenceObject$</value>
|
||||||
|
<value>lecture$</value>
|
||||||
|
<value>workingPaper$</value>
|
||||||
|
<value>preprint$</value>
|
||||||
|
<value>report$</value>
|
||||||
|
<value>annotation$</value>
|
||||||
|
<value>contributionToPeriodical$</value>
|
||||||
|
<value>patent$</value>
|
||||||
|
<value>dataset$</value>
|
||||||
|
<value>other$</value>
|
||||||
|
</list>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- is in collection 123456789/20 (note, list parameter map means multiple collections can be passed) -->
|
||||||
|
<bean id="in-outfit-collection_condition"
|
||||||
|
class="org.dspace.content.logic.condition.InCollectionCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="collections">
|
||||||
|
<list>
|
||||||
|
<value>123456789/20</value>
|
||||||
|
</list>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- has exactly one bitstream in ORIGINAL bundle -->
|
||||||
|
<bean id="has-one-bitstream_condition"
|
||||||
|
class="org.dspace.content.logic.condition.BitstreamCountCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="bundle" value="ORIGINAL"/>
|
||||||
|
<entry key="min" value="1"/>
|
||||||
|
<entry key="max" value="1"/>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- has at least one bitstream in ORIGINAL bundle -->
|
||||||
|
<bean id="has-at-least-one-bitstream_condition"
|
||||||
|
class="org.dspace.content.logic.condition.BitstreamCountCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="bundle" value="ORIGINAL"/>
|
||||||
|
<entry key="min" value="1"/>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="is-archived_condition" class="org.dspace.content.logic.condition.IsArchivedCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map></map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
<bean id="is-withdrawn_condition" class="org.dspace.content.logic.condition.IsWithdrawnCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map></map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- DEFINE OPERATORS
|
||||||
|
Operators can be defined too, if a particular AND or OR statement needs to be re-used a lot, though
|
||||||
|
it may be easier in most cases to turn that into a filter and reference the filter in other sub-statements
|
||||||
|
-->
|
||||||
|
<bean class="org.dspace.content.logic.operator.Or" id="a-common-or_statement">
|
||||||
|
<property name="statements">
|
||||||
|
<list>
|
||||||
|
<ref bean="type-equals-journal-article_condition"/>
|
||||||
|
<ref bean="type-equals-dataset_condition"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- DEFINE FILTERS -->
|
||||||
|
<!-- Note that this filter is almost the same as the above "or" bean but the advantage is we
|
||||||
|
can reference the type_filter directly for item logic *and* as a sub-statement of other filters
|
||||||
|
whereas the operator class can only be a sub-statement
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Example DOI Filter. An item has to pass the filter (filter returns true) to get a DOI.
|
||||||
|
If the filter returns false on an item, minting of a new DOI for that item is prevented. -->
|
||||||
|
<bean id="doi-filter" class="org.dspace.content.logic.DefaultFilter">
|
||||||
|
<property name="statement">
|
||||||
|
<bean class="org.dspace.content.logic.operator.And">
|
||||||
|
<property name="statements">
|
||||||
|
<list>
|
||||||
|
<!-- Make sure the item is archived -->
|
||||||
|
<ref bean="is-archived_condition"/>
|
||||||
|
<!-- Make sure the item is not withdrawn -->
|
||||||
|
<bean class="org.dspace.content.logic.operator.Not">
|
||||||
|
<property name="statements" ref="is-withdrawn_condition"/>
|
||||||
|
</bean>
|
||||||
|
<!-- Don't create new DOIs for items that already have one -->
|
||||||
|
<bean class="org.dspace.content.logic.operator.Not">
|
||||||
|
<property name="statements" ref="dc-identifier-uri-contains-doi_condition"/>
|
||||||
|
</bean>
|
||||||
|
<!-- Create DOIs for items only that do have at least one bitstream. -->
|
||||||
|
<ref bean="has-at-least-one-bitstream_condition"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="type_filter" class="org.dspace.content.logic.DefaultFilter">
|
||||||
|
<property name="statement">
|
||||||
|
<!-- the below is the same as referencing the above, eg:
|
||||||
|
<ref bean="a-common-r_statement"/> -->
|
||||||
|
<bean class="org.dspace.content.logic.operator.Or">
|
||||||
|
<property name="statements">
|
||||||
|
<list>
|
||||||
|
<ref bean="type-equals-journal-article_condition"/>
|
||||||
|
<ref bean="type-equals-dataset_condition"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- A very simple demonstration filter, using the metadata match condition -->
|
||||||
|
<bean id="simple-demo_filter" class="org.dspace.content.logic.DefaultFilter">
|
||||||
|
<property name="statement" ref="title-contains-demo_condition"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- A very simple filter for items with at least one bitstream -->
|
||||||
|
<bean id="has-bitstream_filter" class="org.dspace.content.logic.DefaultFilter">
|
||||||
|
<property name="statement" ref="has-at-least-one-bitstream_condition"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
a more complex example:
|
||||||
|
title contains 'demo' AND (title starts with 'Pattern' OR item is in one of the listed collections)
|
||||||
|
-->
|
||||||
|
<bean id="demo_filter" class="org.dspace.content.logic.DefaultFilter">
|
||||||
|
<property name="statement">
|
||||||
|
<bean class="org.dspace.content.logic.operator.And">
|
||||||
|
<!-- title contains 'demo' AND (the result of the OR substatement is true) -->
|
||||||
|
<property name="statements">
|
||||||
|
<list>
|
||||||
|
<ref bean="title-contains-demo_condition"/>
|
||||||
|
<bean class="org.dspace.content.logic.operator.Or">
|
||||||
|
<!-- title starts with Lily OR the item in one of the listed collections -->
|
||||||
|
<property name="statements">
|
||||||
|
<list>
|
||||||
|
<ref bean="title-starts-with-pattern_condition"/>
|
||||||
|
<bean class="org.dspace.content.logic.condition.InCollectionCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="collections">
|
||||||
|
<list>
|
||||||
|
<value>123456789/3</value>
|
||||||
|
<value>123456789/4</value>
|
||||||
|
</list>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- An example of an OpenAIRE compliance filter based on the same rules in xoai.xml
|
||||||
|
some sub-statements are defined within this bean, and some are referenced from earlier definitions
|
||||||
|
-->
|
||||||
|
<bean id="openaire_filter" class="org.dspace.content.logic.DefaultFilter">
|
||||||
|
<property name="statement">
|
||||||
|
<bean class="org.dspace.content.logic.operator.And">
|
||||||
|
<property name="statements">
|
||||||
|
<list>
|
||||||
|
<!-- Has a non-empty title -->
|
||||||
|
<bean id="has-title_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.title" />
|
||||||
|
<entry key="pattern" value=".*" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
<!-- AND has a non-empty author -->
|
||||||
|
<bean id="has-author_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.contributor.author" />
|
||||||
|
<entry key="pattern" value=".*" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
<!-- AND has a valid DRIVER document type (defined earlier) -->
|
||||||
|
<ref bean="driver-document-type_condition" />
|
||||||
|
<!-- AND (the item is publicly accessible OR withdrawn) -->
|
||||||
|
<bean class="org.dspace.content.logic.operator.Or">
|
||||||
|
<property name="statements">
|
||||||
|
<list>
|
||||||
|
<!-- item is public, defined earlier -->
|
||||||
|
<ref bean="item-is-public_condition" />
|
||||||
|
<!-- OR item is withdrawn, for tombstoning -->
|
||||||
|
<bean class="org.dspace.content.logic.condition.IsWithdrawnCondition">
|
||||||
|
<property name="parameters"><map></map></property>
|
||||||
|
</bean>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
<!-- AND the dc.relation is a valid OpenAIRE identifier
|
||||||
|
(starts with "info:eu-repo/grantAgreement/") -->
|
||||||
|
<bean id="has-openaire-relation_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.relation" />
|
||||||
|
<entry key="pattern" value="^info:eu-repo/grantAgreement/" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="example-doi_filter" class="org.dspace.content.logic.DefaultFilter">
|
||||||
|
<property name="statement">
|
||||||
|
<bean class="org.dspace.content.logic.operator.And">
|
||||||
|
<property name="statements">
|
||||||
|
<list>
|
||||||
|
<!-- Has a non-empty title -->
|
||||||
|
<bean id="has-title_condition"
|
||||||
|
class="org.dspace.content.logic.condition.MetadataValueMatchCondition">
|
||||||
|
<property name="parameters">
|
||||||
|
<map>
|
||||||
|
<entry key="field" value="dc.title" />
|
||||||
|
<entry key="pattern" value=".*" />
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
@@ -15,9 +15,12 @@
|
|||||||
<bean id="selectrevieweractionAPI" class="org.dspace.xmlworkflow.state.actions.processingaction.SelectReviewerAction" scope="prototype">
|
<bean id="selectrevieweractionAPI" class="org.dspace.xmlworkflow.state.actions.processingaction.SelectReviewerAction" scope="prototype">
|
||||||
<property name="role" ref="scoreassignedreviewer"/>
|
<property name="role" ref="scoreassignedreviewer"/>
|
||||||
</bean>
|
</bean>
|
||||||
<bean id="scorereviewactionAPI" class="org.dspace.xmlworkflow.state.actions.processingaction.ScoreReviewAction" scope="prototype"/>
|
<bean id="scorereviewactionAPI" class="org.dspace.xmlworkflow.state.actions.processingaction.ScoreReviewAction" scope="prototype">
|
||||||
|
<property name="descriptionRequired" value="true"/>
|
||||||
|
<property name="maxValue" value="5"/>
|
||||||
|
</bean>
|
||||||
<bean id="evaluationactionAPI" class="org.dspace.xmlworkflow.state.actions.processingaction.ScoreEvaluationAction" scope="prototype">
|
<bean id="evaluationactionAPI" class="org.dspace.xmlworkflow.state.actions.processingaction.ScoreEvaluationAction" scope="prototype">
|
||||||
<property name="minimumAcceptanceScore" value="50" />
|
<property name="minimumAcceptanceScore" value="3" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
@@ -63,6 +66,12 @@
|
|||||||
<property name="requiresUI" value="true"/>
|
<property name="requiresUI" value="true"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="ratingreviewaction" class="org.dspace.xmlworkflow.state.actions.WorkflowActionConfig" scope="prototype">
|
||||||
|
<constructor-arg type="java.lang.String" value="ratingreviewaction"/>
|
||||||
|
<property name="processingAction" ref="ratingreviewactionAPI" />
|
||||||
|
<property name="requiresUI" value="true"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!--Autmatic step that evaluates scores (workflow.score) and checks if they match the configured minimum for archiving -->
|
<!--Autmatic step that evaluates scores (workflow.score) and checks if they match the configured minimum for archiving -->
|
||||||
<bean id="evaluationaction" class="org.dspace.xmlworkflow.state.actions.WorkflowActionConfig" scope="prototype">
|
<bean id="evaluationaction" class="org.dspace.xmlworkflow.state.actions.WorkflowActionConfig" scope="prototype">
|
||||||
<constructor-arg type="java.lang.String" value="evaluationaction"/>
|
<constructor-arg type="java.lang.String" value="evaluationaction"/>
|
||||||
|
@@ -153,6 +153,7 @@
|
|||||||
<bean id="scoreassignedreviewer" class="org.dspace.xmlworkflow.Role">
|
<bean id="scoreassignedreviewer" class="org.dspace.xmlworkflow.Role">
|
||||||
<property name="scope" value="#{ T(org.dspace.xmlworkflow.Role.Scope).ITEM}"/>
|
<property name="scope" value="#{ T(org.dspace.xmlworkflow.Role.Scope).ITEM}"/>
|
||||||
<property name="name" value="Reviewer"/>
|
<property name="name" value="Reviewer"/>
|
||||||
|
<property name="deleteTemporaryGroup" value="true"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user