Skip to content

Commit

Permalink
Merge pull request #2115 from mwoodiupui/DS-3951
Browse files Browse the repository at this point in the history
[DS-3951] Send Request Copy email to multiple recipients, and some new recipient strategies
  • Loading branch information
abollini committed Sep 15, 2022
2 parents 6b1fae1 + 07a4649 commit 3b23ff9
Show file tree
Hide file tree
Showing 14 changed files with 443 additions and 94 deletions.
@@ -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.app.requestitem;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.springframework.lang.NonNull;

/**
* Derive request recipients from groups of the Collection which owns an Item.
* The list will include all members of the administrators group. If the
* resulting list is empty, delegates to {@link RequestItemHelpdeskStrategy}.
*
* @author Mark H. Wood <mwood@iupui.edu>
*/
public class CollectionAdministratorsRequestItemStrategy
extends RequestItemHelpdeskStrategy {
@Override
@NonNull
public List<RequestItemAuthor> getRequestItemAuthor(Context context,
Item item)
throws SQLException {
List<RequestItemAuthor> recipients = new ArrayList<>();
Collection collection = item.getOwningCollection();
for (EPerson admin : collection.getAdministrators().getMembers()) {
recipients.add(new RequestItemAuthor(admin));
}
if (recipients.isEmpty()) {
return super.getRequestItemAuthor(context, item);
} else {
return recipients;
}
}
}
@@ -0,0 +1,61 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.requestitem;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.dspace.content.Item;
import org.dspace.core.Context;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;

/**
* Assemble a list of recipients from the results of other strategies.
* The list of strategy classes is injected as the constructor argument
* {@code strategies}.
* If the strategy list is not configured, returns an empty List.
*
* @author Mark H. Wood <mwood@iupui.edu>
*/
public class CombiningRequestItemStrategy
implements RequestItemAuthorExtractor {
/** The strategies to combine. */
private final List<RequestItemAuthorExtractor> strategies;

/**
* Initialize a combination of strategies.
* @param strategies the author extraction strategies to combine.
*/
public CombiningRequestItemStrategy(@NonNull List<RequestItemAuthorExtractor> strategies) {
Assert.notNull(strategies, "Strategy list may not be null");
this.strategies = strategies;
}

/**
* Do not call.
* @throws IllegalArgumentException always
*/
private CombiningRequestItemStrategy() {
throw new IllegalArgumentException();
}

@Override
@NonNull
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
throws SQLException {
List<RequestItemAuthor> recipients = new ArrayList<>();

for (RequestItemAuthorExtractor strategy : strategies) {
recipients.addAll(strategy.getRequestItemAuthor(context, item));
}

return recipients;
}
}
Expand Up @@ -27,7 +27,7 @@
import org.dspace.core.ReloadableEntity;

/**
* Object representing an Item Request
* Object representing an Item Request.
*/
@Entity
@Table(name = "requestitem")
Expand Down Expand Up @@ -94,6 +94,9 @@ void setAllfiles(boolean allfiles) {
this.allfiles = allfiles;
}

/**
* @return {@code true} if all of the Item's files are requested.
*/
public boolean isAllfiles() {
return allfiles;
}
Expand All @@ -102,6 +105,9 @@ void setReqMessage(String reqMessage) {
this.reqMessage = reqMessage;
}

/**
* @return a message from the requester.
*/
public String getReqMessage() {
return reqMessage;
}
Expand All @@ -110,6 +116,9 @@ void setReqName(String reqName) {
this.reqName = reqName;
}

/**
* @return Human-readable name of the user requesting access.
*/
public String getReqName() {
return reqName;
}
Expand All @@ -118,6 +127,9 @@ void setReqEmail(String reqEmail) {
this.reqEmail = reqEmail;
}

/**
* @return address of the user requesting access.
*/
public String getReqEmail() {
return reqEmail;
}
Expand All @@ -126,6 +138,9 @@ void setToken(String token) {
this.token = token;
}

/**
* @return a unique request identifier which can be emailed.
*/
public String getToken() {
return token;
}
Expand Down
Expand Up @@ -11,20 +11,31 @@

/**
* Simple DTO to transfer data about the corresponding author for the Request
* Copy feature
* Copy feature.
*
* @author Andrea Bollini
*/
public class RequestItemAuthor {
private String fullName;
private String email;
private final String fullName;
private final String email;

/**
* Construct an author record from given data.
*
* @param fullName the author's full name.
* @param email the author's email address.
*/
public RequestItemAuthor(String fullName, String email) {
super();
this.fullName = fullName;
this.email = email;
}

/**
* Construct an author from an EPerson's metadata.
*
* @param ePerson the EPerson.
*/
public RequestItemAuthor(EPerson ePerson) {
super();
this.fullName = ePerson.getFullName();
Expand Down
Expand Up @@ -8,26 +8,28 @@
package org.dspace.app.requestitem;

import java.sql.SQLException;
import java.util.List;

import org.dspace.content.Item;
import org.dspace.core.Context;
import org.springframework.lang.NonNull;

/**
* Interface to abstract the strategy for select the author to contact for
* request copy
* Interface to abstract the strategy for selecting the author to contact for
* request copy.
*
* @author Andrea Bollini
*/
public interface RequestItemAuthorExtractor {

/**
* Retrieve the auhtor to contact for a request copy of the give item.
* Retrieve the author to contact for requesting a copy of the given item.
*
* @param context DSpace context object
* @param item item to request
* @return An object containing name an email address to send the request to
* or null if no valid email address was found.
* @return Names and email addresses to send the request to.
* @throws SQLException if database error
*/
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) throws SQLException;
@NonNull
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
throws SQLException;
}
Expand Up @@ -72,28 +72,48 @@ private RequestItemEmailNotifier() {}
static public void sendRequest(Context context, RequestItem ri, String responseLink)
throws IOException, SQLException {
// Who is making this request?
RequestItemAuthor author = requestItemAuthorExtractor
List<RequestItemAuthor> authors = requestItemAuthorExtractor
.getRequestItemAuthor(context, ri.getItem());
String authorEmail = author.getEmail();
String authorName = author.getFullName();

// Build an email to the approver.
Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(),
"request_item.author"));
email.addRecipient(authorEmail);
for (RequestItemAuthor author : authors) {
email.addRecipient(author.getEmail());
}
email.setReplyTo(ri.getReqEmail()); // Requester's address

email.addArgument(ri.getReqName()); // {0} Requester's name

email.addArgument(ri.getReqEmail()); // {1} Requester's address

email.addArgument(ri.isAllfiles() // {2} All bitstreams or just one?
? I18nUtil.getMessage("itemRequest.all") : ri.getBitstream().getName());
email.addArgument(handleService.getCanonicalForm(ri.getItem().getHandle()));

email.addArgument(handleService.getCanonicalForm(ri.getItem().getHandle())); // {3}

email.addArgument(ri.getItem().getName()); // {4} requested item's title

email.addArgument(ri.getReqMessage()); // {5} message from requester

email.addArgument(responseLink); // {6} Link back to DSpace for action
email.addArgument(authorName); // {7} corresponding author name
email.addArgument(authorEmail); // {8} corresponding author email
email.addArgument(configurationService.getProperty("dspace.name"));
email.addArgument(configurationService.getProperty("mail.helpdesk"));

StringBuilder names = new StringBuilder();
StringBuilder addresses = new StringBuilder();
for (RequestItemAuthor author : authors) {
if (names.length() > 0) {
names.append("; ");
addresses.append("; ");
}
names.append(author.getFullName());
addresses.append(author.getEmail());
}
email.addArgument(names.toString()); // {7} corresponding author name
email.addArgument(addresses.toString()); // {8} corresponding author email

email.addArgument(configurationService.getProperty("dspace.name")); // {9}

email.addArgument(configurationService.getProperty("mail.helpdesk")); // {10}

// Send the email.
try {
Expand Down
Expand Up @@ -8,6 +8,8 @@
package org.dspace.app.requestitem;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.dspace.content.Item;
Expand All @@ -16,11 +18,11 @@
import org.dspace.eperson.EPerson;
import org.dspace.eperson.service.EPersonService;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;

/**
* RequestItem strategy to allow DSpace support team's helpdesk to receive requestItem request
* RequestItem strategy to allow DSpace support team's helpdesk to receive requestItem request.
* With this enabled, then the Item author/submitter doesn't receive the request, but the helpdesk instead does.
*
* Failover to the RequestItemSubmitterStrategy, which means the submitter would get the request if there is no
Expand All @@ -33,19 +35,24 @@ public class RequestItemHelpdeskStrategy extends RequestItemSubmitterStrategy {
@Autowired(required = true)
protected EPersonService ePersonService;

@Autowired(required = true)
private ConfigurationService configuration;

public RequestItemHelpdeskStrategy() {
}

@Override
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) throws SQLException {
ConfigurationService configurationService
= DSpaceServicesFactory.getInstance().getConfigurationService();
boolean helpdeskOverridesSubmitter = configurationService
@NonNull
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
throws SQLException {
boolean helpdeskOverridesSubmitter = configuration
.getBooleanProperty("request.item.helpdesk.override", false);
String helpDeskEmail = configurationService.getProperty("mail.helpdesk");
String helpDeskEmail = configuration.getProperty("mail.helpdesk");

if (helpdeskOverridesSubmitter && StringUtils.isNotBlank(helpDeskEmail)) {
return getHelpDeskPerson(context, helpDeskEmail);
List<RequestItemAuthor> authors = new ArrayList<>(1);
authors.add(getHelpDeskPerson(context, helpDeskEmail));
return authors;
} else {
//Fallback to default logic (author of Item) if helpdesk isn't fully enabled or setup
return super.getRequestItemAuthor(context, item);
Expand Down

0 comments on commit 3b23ff9

Please sign in to comment.