mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 18:14:26 +00:00
Merge branch 'main' of https://github.com/DSpace/DSpace into DURACOM-86
This commit is contained in:
@@ -548,17 +548,11 @@
|
|||||||
<groupId>com.ibm.icu</groupId>
|
<groupId>com.ibm.icu</groupId>
|
||||||
<artifactId>icu4j</artifactId>
|
<artifactId>icu4j</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Codebase at https://github.com/OCLC-Research/oaiharvester2/ -->
|
<!-- Codebase at https://github.com/DSpace/oclc-harvester2 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dspace</groupId>
|
<groupId>org.dspace</groupId>
|
||||||
<artifactId>oclc-harvester2</artifactId>
|
<artifactId>oclc-harvester2</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Xalan is REQUIRED by 'oclc-harvester2' listed above (OAI harvesting fails without it).
|
|
||||||
Please do NOT use Xalan in DSpace codebase as it is not well maintained. -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>xalan</groupId>
|
|
||||||
<artifactId>xalan</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dspace</groupId>
|
<groupId>org.dspace</groupId>
|
||||||
<artifactId>dspace-services</artifactId>
|
<artifactId>dspace-services</artifactId>
|
||||||
|
@@ -14,6 +14,7 @@ import java.util.Locale;
|
|||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
import org.apache.commons.cli.DefaultParser;
|
import org.apache.commons.cli.DefaultParser;
|
||||||
|
import org.apache.commons.cli.HelpFormatter;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
@@ -69,19 +70,41 @@ public final class CreateAdministrator {
|
|||||||
|
|
||||||
options.addOption("e", "email", true, "administrator email address");
|
options.addOption("e", "email", true, "administrator email address");
|
||||||
options.addOption("f", "first", true, "administrator first name");
|
options.addOption("f", "first", true, "administrator first name");
|
||||||
|
options.addOption("h", "help", false, "explain create-administrator options");
|
||||||
options.addOption("l", "last", true, "administrator last name");
|
options.addOption("l", "last", true, "administrator last name");
|
||||||
options.addOption("c", "language", true, "administrator language");
|
options.addOption("c", "language", true, "administrator language");
|
||||||
options.addOption("p", "password", true, "administrator password");
|
options.addOption("p", "password", true, "administrator password");
|
||||||
|
|
||||||
CommandLine line = parser.parse(options, argv);
|
CommandLine line = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
line = parser.parse(options, argv);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
System.out.println(e.getMessage() + "\nTry \"dspace create-administrator -h\" to print help information.");
|
||||||
|
System.exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (line.hasOption("e") && line.hasOption("f") && line.hasOption("l") &&
|
if (line.hasOption("e") && line.hasOption("f") && line.hasOption("l") &&
|
||||||
line.hasOption("c") && line.hasOption("p")) {
|
line.hasOption("c") && line.hasOption("p")) {
|
||||||
ca.createAdministrator(line.getOptionValue("e"),
|
ca.createAdministrator(line.getOptionValue("e"),
|
||||||
line.getOptionValue("f"), line.getOptionValue("l"),
|
line.getOptionValue("f"), line.getOptionValue("l"),
|
||||||
line.getOptionValue("c"), line.getOptionValue("p"));
|
line.getOptionValue("c"), line.getOptionValue("p"));
|
||||||
|
} else if (line.hasOption("h")) {
|
||||||
|
String header = "\nA command-line tool for creating an initial administrator for setting up a" +
|
||||||
|
" DSpace site. Unless all the required parameters are passed it will" +
|
||||||
|
" prompt for an e-mail address, last name, first name and password from" +
|
||||||
|
" standard input.. An administrator group is then created and the data passed" +
|
||||||
|
" in used to create an e-person in that group.\n\n";
|
||||||
|
String footer = "\n";
|
||||||
|
HelpFormatter formatter = new HelpFormatter();
|
||||||
|
formatter.printHelp("dspace create-administrator", header, options, footer, true);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
ca.negotiateAdministratorDetails();
|
ca.negotiateAdministratorDetails(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,20 +126,20 @@ public final class CreateAdministrator {
|
|||||||
*
|
*
|
||||||
* @throws Exception if error
|
* @throws Exception if error
|
||||||
*/
|
*/
|
||||||
protected void negotiateAdministratorDetails()
|
protected void negotiateAdministratorDetails(CommandLine line)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Console console = System.console();
|
Console console = System.console();
|
||||||
|
|
||||||
System.out.println("Creating an initial administrator account");
|
System.out.println("Creating an initial administrator account");
|
||||||
|
|
||||||
boolean dataOK = false;
|
String email = line.getOptionValue('e');
|
||||||
|
String firstName = line.getOptionValue('f');
|
||||||
String email = null;
|
String lastName = line.getOptionValue('l');
|
||||||
String firstName = null;
|
|
||||||
String lastName = null;
|
|
||||||
char[] password1 = null;
|
|
||||||
char[] password2 = null;
|
|
||||||
String language = I18nUtil.getDefaultLocale().getLanguage();
|
String language = I18nUtil.getDefaultLocale().getLanguage();
|
||||||
|
ConfigurationService cfg = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
boolean flag = line.hasOption('p');
|
||||||
|
char[] password = null;
|
||||||
|
boolean dataOK = line.hasOption('f') && line.hasOption('e') && line.hasOption('l');
|
||||||
|
|
||||||
while (!dataOK) {
|
while (!dataOK) {
|
||||||
System.out.print("E-mail address: ");
|
System.out.print("E-mail address: ");
|
||||||
@@ -147,8 +170,6 @@ public final class CreateAdministrator {
|
|||||||
if (lastName != null) {
|
if (lastName != null) {
|
||||||
lastName = lastName.trim();
|
lastName = lastName.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigurationService cfg = DSpaceServicesFactory.getInstance().getConfigurationService();
|
|
||||||
if (cfg.hasProperty("webui.supported.locales")) {
|
if (cfg.hasProperty("webui.supported.locales")) {
|
||||||
System.out.println("Select one of the following languages: "
|
System.out.println("Select one of the following languages: "
|
||||||
+ cfg.getProperty("webui.supported.locales"));
|
+ cfg.getProperty("webui.supported.locales"));
|
||||||
@@ -163,20 +184,6 @@ public final class CreateAdministrator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Password will not display on screen.");
|
|
||||||
System.out.print("Password: ");
|
|
||||||
System.out.flush();
|
|
||||||
|
|
||||||
password1 = console.readPassword();
|
|
||||||
|
|
||||||
System.out.print("Again to confirm: ");
|
|
||||||
System.out.flush();
|
|
||||||
|
|
||||||
password2 = console.readPassword();
|
|
||||||
|
|
||||||
//TODO real password validation
|
|
||||||
if (password1.length > 1 && Arrays.equals(password1, password2)) {
|
|
||||||
// password OK
|
|
||||||
System.out.print("Is the above data correct? (y or n): ");
|
System.out.print("Is the above data correct? (y or n): ");
|
||||||
System.out.flush();
|
System.out.flush();
|
||||||
|
|
||||||
@@ -188,19 +195,46 @@ public final class CreateAdministrator {
|
|||||||
dataOK = true;
|
dataOK = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!flag) {
|
||||||
|
password = getPassword(console);
|
||||||
|
if (password == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
password = line.getOptionValue("p").toCharArray();
|
||||||
|
}
|
||||||
|
// if we make it to here, we are ready to create an administrator
|
||||||
|
createAdministrator(email, firstName, lastName, language, String.valueOf(password));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private char[] getPassword(Console console) {
|
||||||
|
char[] password1 = null;
|
||||||
|
char[] password2 = null;
|
||||||
|
System.out.println("Password will not display on screen.");
|
||||||
|
System.out.print("Password: ");
|
||||||
|
System.out.flush();
|
||||||
|
|
||||||
|
password1 = console.readPassword();
|
||||||
|
|
||||||
|
System.out.print("Again to confirm: ");
|
||||||
|
System.out.flush();
|
||||||
|
|
||||||
|
password2 = console.readPassword();
|
||||||
|
|
||||||
|
// TODO real password validation
|
||||||
|
if (password1.length > 1 && Arrays.equals(password1, password2)) {
|
||||||
|
// password OK
|
||||||
|
Arrays.fill(password2, ' ');
|
||||||
|
return password1;
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Passwords don't match");
|
System.out.println("Passwords don't match");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we make it to here, we are ready to create an administrator
|
|
||||||
createAdministrator(email, firstName, lastName, language, String.valueOf(password1));
|
|
||||||
|
|
||||||
//Cleaning arrays that held password
|
|
||||||
Arrays.fill(password1, ' ');
|
|
||||||
Arrays.fill(password2, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the administrator with the given details. If the user
|
* Create the administrator with the given details. If the user
|
||||||
* already exists then they are simply upped to administrator status
|
* already exists then they are simply upped to administrator status
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
@@ -27,7 +27,7 @@ import org.dspace.core.Context;
|
|||||||
import org.dspace.core.ReloadableEntity;
|
import org.dspace.core.ReloadableEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object representing an Item Request
|
* Object representing an Item Request.
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "requestitem")
|
@Table(name = "requestitem")
|
||||||
@@ -94,6 +94,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.allfiles = allfiles;
|
this.allfiles = allfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true} if all of the Item's files are requested.
|
||||||
|
*/
|
||||||
public boolean isAllfiles() {
|
public boolean isAllfiles() {
|
||||||
return allfiles;
|
return allfiles;
|
||||||
}
|
}
|
||||||
@@ -102,6 +105,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.reqMessage = reqMessage;
|
this.reqMessage = reqMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a message from the requester.
|
||||||
|
*/
|
||||||
public String getReqMessage() {
|
public String getReqMessage() {
|
||||||
return reqMessage;
|
return reqMessage;
|
||||||
}
|
}
|
||||||
@@ -110,6 +116,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.reqName = reqName;
|
this.reqName = reqName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Human-readable name of the user requesting access.
|
||||||
|
*/
|
||||||
public String getReqName() {
|
public String getReqName() {
|
||||||
return reqName;
|
return reqName;
|
||||||
}
|
}
|
||||||
@@ -118,6 +127,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.reqEmail = reqEmail;
|
this.reqEmail = reqEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return address of the user requesting access.
|
||||||
|
*/
|
||||||
public String getReqEmail() {
|
public String getReqEmail() {
|
||||||
return reqEmail;
|
return reqEmail;
|
||||||
}
|
}
|
||||||
@@ -126,6 +138,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a unique request identifier which can be emailed.
|
||||||
|
*/
|
||||||
public String getToken() {
|
public String getToken() {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
@@ -11,20 +11,31 @@ import org.dspace.eperson.EPerson;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple DTO to transfer data about the corresponding author for the Request
|
* Simple DTO to transfer data about the corresponding author for the Request
|
||||||
* Copy feature
|
* Copy feature.
|
||||||
*
|
*
|
||||||
* @author Andrea Bollini
|
* @author Andrea Bollini
|
||||||
*/
|
*/
|
||||||
public class RequestItemAuthor {
|
public class RequestItemAuthor {
|
||||||
private String fullName;
|
private final String fullName;
|
||||||
private String email;
|
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) {
|
public RequestItemAuthor(String fullName, String email) {
|
||||||
super();
|
super();
|
||||||
this.fullName = fullName;
|
this.fullName = fullName;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an author from an EPerson's metadata.
|
||||||
|
*
|
||||||
|
* @param ePerson the EPerson.
|
||||||
|
*/
|
||||||
public RequestItemAuthor(EPerson ePerson) {
|
public RequestItemAuthor(EPerson ePerson) {
|
||||||
super();
|
super();
|
||||||
this.fullName = ePerson.getFullName();
|
this.fullName = ePerson.getFullName();
|
||||||
|
@@ -8,26 +8,28 @@
|
|||||||
package org.dspace.app.requestitem;
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to abstract the strategy for select the author to contact for
|
* Interface to abstract the strategy for selecting the author to contact for
|
||||||
* request copy
|
* request copy.
|
||||||
*
|
*
|
||||||
* @author Andrea Bollini
|
* @author Andrea Bollini
|
||||||
*/
|
*/
|
||||||
public interface RequestItemAuthorExtractor {
|
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 context DSpace context object
|
||||||
* @param item item to request
|
* @param item item to request
|
||||||
* @return An object containing name an email address to send the request to
|
* @return Names and email addresses to send the request to.
|
||||||
* or null if no valid email address was found.
|
|
||||||
* @throws SQLException if database error
|
* @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;
|
||||||
}
|
}
|
||||||
|
@@ -72,28 +72,48 @@ public class RequestItemEmailNotifier {
|
|||||||
static public void sendRequest(Context context, RequestItem ri, String responseLink)
|
static public void sendRequest(Context context, RequestItem ri, String responseLink)
|
||||||
throws IOException, SQLException {
|
throws IOException, SQLException {
|
||||||
// Who is making this request?
|
// Who is making this request?
|
||||||
RequestItemAuthor author = requestItemAuthorExtractor
|
List<RequestItemAuthor> authors = requestItemAuthorExtractor
|
||||||
.getRequestItemAuthor(context, ri.getItem());
|
.getRequestItemAuthor(context, ri.getItem());
|
||||||
String authorEmail = author.getEmail();
|
|
||||||
String authorName = author.getFullName();
|
|
||||||
|
|
||||||
// Build an email to the approver.
|
// Build an email to the approver.
|
||||||
Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(),
|
Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(),
|
||||||
"request_item.author"));
|
"request_item.author"));
|
||||||
email.addRecipient(authorEmail);
|
for (RequestItemAuthor author : authors) {
|
||||||
|
email.addRecipient(author.getEmail());
|
||||||
|
}
|
||||||
email.setReplyTo(ri.getReqEmail()); // Requester's address
|
email.setReplyTo(ri.getReqEmail()); // Requester's address
|
||||||
|
|
||||||
email.addArgument(ri.getReqName()); // {0} Requester's name
|
email.addArgument(ri.getReqName()); // {0} Requester's name
|
||||||
|
|
||||||
email.addArgument(ri.getReqEmail()); // {1} Requester's address
|
email.addArgument(ri.getReqEmail()); // {1} Requester's address
|
||||||
|
|
||||||
email.addArgument(ri.isAllfiles() // {2} All bitstreams or just one?
|
email.addArgument(ri.isAllfiles() // {2} All bitstreams or just one?
|
||||||
? I18nUtil.getMessage("itemRequest.all") : ri.getBitstream().getName());
|
? 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.getItem().getName()); // {4} requested item's title
|
||||||
|
|
||||||
email.addArgument(ri.getReqMessage()); // {5} message from requester
|
email.addArgument(ri.getReqMessage()); // {5} message from requester
|
||||||
|
|
||||||
email.addArgument(responseLink); // {6} Link back to DSpace for action
|
email.addArgument(responseLink); // {6} Link back to DSpace for action
|
||||||
email.addArgument(authorName); // {7} corresponding author name
|
|
||||||
email.addArgument(authorEmail); // {8} corresponding author email
|
StringBuilder names = new StringBuilder();
|
||||||
email.addArgument(configurationService.getProperty("dspace.name"));
|
StringBuilder addresses = new StringBuilder();
|
||||||
email.addArgument(configurationService.getProperty("mail.helpdesk"));
|
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.
|
// Send the email.
|
||||||
try {
|
try {
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
package org.dspace.app.requestitem;
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
@@ -16,11 +18,11 @@ import org.dspace.core.I18nUtil;
|
|||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.service.EPersonService;
|
import org.dspace.eperson.service.EPersonService;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.
|
* 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
|
* Failover to the RequestItemSubmitterStrategy, which means the submitter would get the request if there is no
|
||||||
@@ -33,19 +35,24 @@ public class RequestItemHelpdeskStrategy extends RequestItemSubmitterStrategy {
|
|||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected EPersonService ePersonService;
|
protected EPersonService ePersonService;
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
private ConfigurationService configuration;
|
||||||
|
|
||||||
public RequestItemHelpdeskStrategy() {
|
public RequestItemHelpdeskStrategy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) throws SQLException {
|
@NonNull
|
||||||
ConfigurationService configurationService
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
throws SQLException {
|
||||||
boolean helpdeskOverridesSubmitter = configurationService
|
boolean helpdeskOverridesSubmitter = configuration
|
||||||
.getBooleanProperty("request.item.helpdesk.override", false);
|
.getBooleanProperty("request.item.helpdesk.override", false);
|
||||||
String helpDeskEmail = configurationService.getProperty("mail.helpdesk");
|
String helpDeskEmail = configuration.getProperty("mail.helpdesk");
|
||||||
|
|
||||||
if (helpdeskOverridesSubmitter && StringUtils.isNotBlank(helpDeskEmail)) {
|
if (helpdeskOverridesSubmitter && StringUtils.isNotBlank(helpDeskEmail)) {
|
||||||
return getHelpDeskPerson(context, helpDeskEmail);
|
List<RequestItemAuthor> authors = new ArrayList<>(1);
|
||||||
|
authors.add(getHelpDeskPerson(context, helpDeskEmail));
|
||||||
|
return authors;
|
||||||
} else {
|
} else {
|
||||||
//Fallback to default logic (author of Item) if helpdesk isn't fully enabled or setup
|
//Fallback to default logic (author of Item) if helpdesk isn't fully enabled or setup
|
||||||
return super.getRequestItemAuthor(context, item);
|
return super.getRequestItemAuthor(context, item);
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
package org.dspace.app.requestitem;
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -16,12 +18,13 @@ import org.dspace.content.MetadataValue;
|
|||||||
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.core.I18nUtil;
|
import org.dspace.core.I18nUtil;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to look to an item metadata for the corresponding author name and email.
|
* Try to look to an item metadata for the corresponding author name and email.
|
||||||
* Failover to the RequestItemSubmitterStrategy
|
* Failover to the RequestItemSubmitterStrategy.
|
||||||
*
|
*
|
||||||
* @author Andrea Bollini
|
* @author Andrea Bollini
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +33,9 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
|
|||||||
protected String emailMetadata;
|
protected String emailMetadata;
|
||||||
protected String fullNameMetadata;
|
protected String fullNameMetadata;
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
protected ConfigurationService configurationService;
|
||||||
|
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected ItemService itemService;
|
protected ItemService itemService;
|
||||||
|
|
||||||
@@ -37,59 +43,72 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
|
@NonNull
|
||||||
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
RequestItemAuthor author = null;
|
List<RequestItemAuthor> authors;
|
||||||
if (emailMetadata != null) {
|
if (emailMetadata != null) {
|
||||||
List<MetadataValue> vals = itemService.getMetadataByMetadataString(item, emailMetadata);
|
List<MetadataValue> vals = itemService.getMetadataByMetadataString(item, emailMetadata);
|
||||||
if (vals.size() > 0) {
|
List<MetadataValue> nameVals;
|
||||||
String email = vals.iterator().next().getValue();
|
if (null != fullNameMetadata) {
|
||||||
|
nameVals = itemService.getMetadataByMetadataString(item, fullNameMetadata);
|
||||||
|
} else {
|
||||||
|
nameVals = Collections.EMPTY_LIST;
|
||||||
|
}
|
||||||
|
boolean useNames = vals.size() == nameVals.size();
|
||||||
|
if (!vals.isEmpty()) {
|
||||||
|
authors = new ArrayList<>(vals.size());
|
||||||
|
for (int authorIndex = 0; authorIndex < vals.size(); authorIndex++) {
|
||||||
|
String email = vals.get(authorIndex).getValue();
|
||||||
String fullname = null;
|
String fullname = null;
|
||||||
if (fullNameMetadata != null) {
|
if (useNames) {
|
||||||
List<MetadataValue> nameVals = itemService.getMetadataByMetadataString(item, fullNameMetadata);
|
fullname = nameVals.get(authorIndex).getValue();
|
||||||
if (nameVals.size() > 0) {
|
|
||||||
fullname = nameVals.iterator().next().getValue();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isBlank(fullname)) {
|
if (StringUtils.isBlank(fullname)) {
|
||||||
fullname = I18nUtil
|
fullname = I18nUtil.getMessage(
|
||||||
.getMessage(
|
|
||||||
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
|
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
|
||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
author = new RequestItemAuthor(fullname, email);
|
RequestItemAuthor author = new RequestItemAuthor(
|
||||||
return author;
|
fullname, email);
|
||||||
|
authors.add(author);
|
||||||
|
}
|
||||||
|
return authors;
|
||||||
|
} else {
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Uses the basic strategy to look for the original submitter
|
// Uses the basic strategy to look for the original submitter
|
||||||
author = super.getRequestItemAuthor(context, item);
|
authors = super.getRequestItemAuthor(context, item);
|
||||||
// Is the author or their email null. If so get the help desk or admin name and email
|
|
||||||
if (null == author || null == author.getEmail()) {
|
// Remove from the list authors that do not have email addresses.
|
||||||
String email = null;
|
for (RequestItemAuthor author : authors) {
|
||||||
String name = null;
|
if (null == author.getEmail()) {
|
||||||
//First get help desk name and email
|
authors.remove(author);
|
||||||
email = DSpaceServicesFactory.getInstance()
|
|
||||||
.getConfigurationService().getProperty("mail.helpdesk");
|
|
||||||
name = DSpaceServicesFactory.getInstance()
|
|
||||||
.getConfigurationService().getProperty("mail.helpdesk.name");
|
|
||||||
// If help desk mail is null get the mail and name of admin
|
|
||||||
if (email == null) {
|
|
||||||
email = DSpaceServicesFactory.getInstance()
|
|
||||||
.getConfigurationService().getProperty("mail.admin");
|
|
||||||
name = DSpaceServicesFactory.getInstance()
|
|
||||||
.getConfigurationService().getProperty("mail.admin.name");
|
|
||||||
}
|
}
|
||||||
author = new RequestItemAuthor(name, email);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return author;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEmailMetadata(String emailMetadata) {
|
if (authors.isEmpty()) { // No author email addresses! Fall back
|
||||||
|
//First get help desk name and email
|
||||||
|
String email = configurationService.getProperty("mail.helpdesk");
|
||||||
|
String name = configurationService.getProperty("mail.helpdesk.name");
|
||||||
|
// If help desk mail is null get the mail and name of admin
|
||||||
|
if (email == null) {
|
||||||
|
email = configurationService.getProperty("mail.admin");
|
||||||
|
name = configurationService.getProperty("mail.admin.name");
|
||||||
|
}
|
||||||
|
authors.add(new RequestItemAuthor(name, email));
|
||||||
|
}
|
||||||
|
return authors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmailMetadata(@NonNull String emailMetadata) {
|
||||||
this.emailMetadata = emailMetadata;
|
this.emailMetadata = emailMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFullNameMetadata(String fullNameMetadata) {
|
public void setFullNameMetadata(@NonNull String fullNameMetadata) {
|
||||||
this.fullNameMetadata = fullNameMetadata;
|
this.fullNameMetadata = fullNameMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,10 +8,13 @@
|
|||||||
package org.dspace.app.requestitem;
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic strategy that looks to the original submitter.
|
* Basic strategy that looks to the original submitter.
|
||||||
@@ -24,21 +27,23 @@ public class RequestItemSubmitterStrategy implements RequestItemAuthorExtractor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the submitter of an Item as RequestItemAuthor or null if the
|
* Returns the submitter of an Item as RequestItemAuthor or an empty List if
|
||||||
* Submitter is deleted.
|
* the Submitter is deleted.
|
||||||
*
|
*
|
||||||
* @return The submitter of the item or null if the submitter is deleted
|
* @return The submitter of the item or empty List if the submitter is deleted
|
||||||
* @throws SQLException if database error
|
* @throws SQLException if database error
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
|
@NonNull
|
||||||
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
EPerson submitter = item.getSubmitter();
|
EPerson submitter = item.getSubmitter();
|
||||||
RequestItemAuthor author = null;
|
List<RequestItemAuthor> authors = new ArrayList<>(1);
|
||||||
if (null != submitter) {
|
if (null != submitter) {
|
||||||
author = new RequestItemAuthor(
|
RequestItemAuthor author = new RequestItemAuthor(
|
||||||
submitter.getFullName(), submitter.getEmail());
|
submitter.getFullName(), submitter.getEmail());
|
||||||
|
authors.add(author);
|
||||||
}
|
}
|
||||||
return author;
|
return authors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,9 +14,7 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -465,17 +463,17 @@ public abstract class AbstractMETSDisseminator
|
|||||||
Utils.copy(input, zip);
|
Utils.copy(input, zip);
|
||||||
input.close();
|
input.close();
|
||||||
} else {
|
} else {
|
||||||
log.warn("Adding zero-length file for Bitstream, SID="
|
log.warn("Adding zero-length file for Bitstream, uuid="
|
||||||
+ String.valueOf(bitstream.getSequenceID())
|
+ String.valueOf(bitstream.getID())
|
||||||
+ ", not authorized for READ.");
|
+ ", not authorized for READ.");
|
||||||
}
|
}
|
||||||
zip.closeEntry();
|
zip.closeEntry();
|
||||||
} else if (unauth != null && unauth.equalsIgnoreCase("skip")) {
|
} else if (unauth != null && unauth.equalsIgnoreCase("skip")) {
|
||||||
log.warn("Skipping Bitstream, SID=" + String
|
log.warn("Skipping Bitstream, uuid=" + String
|
||||||
.valueOf(bitstream.getSequenceID()) + ", not authorized for READ.");
|
.valueOf(bitstream.getID()) + ", not authorized for READ.");
|
||||||
} else {
|
} else {
|
||||||
throw new AuthorizeException(
|
throw new AuthorizeException(
|
||||||
"Not authorized to read Bitstream, SID=" + String.valueOf(bitstream.getSequenceID()));
|
"Not authorized to read Bitstream, uuid=" + String.valueOf(bitstream.getID()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -896,12 +894,12 @@ public abstract class AbstractMETSDisseminator
|
|||||||
continue;
|
continue;
|
||||||
} else if (!(unauth != null && unauth.equalsIgnoreCase("zero"))) {
|
} else if (!(unauth != null && unauth.equalsIgnoreCase("zero"))) {
|
||||||
throw new AuthorizeException(
|
throw new AuthorizeException(
|
||||||
"Not authorized to read Bitstream, SID=" + String.valueOf(bitstream.getSequenceID()));
|
"Not authorized to read Bitstream, uuid=" + String.valueOf(bitstream.getID()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String sid = String.valueOf(bitstream.getSequenceID());
|
String uuid = String.valueOf(bitstream.getID());
|
||||||
String fileID = bitstreamIDstart + sid;
|
String fileID = bitstreamIDstart + uuid;
|
||||||
edu.harvard.hul.ois.mets.File file = new edu.harvard.hul.ois.mets.File();
|
edu.harvard.hul.ois.mets.File file = new edu.harvard.hul.ois.mets.File();
|
||||||
file.setID(fileID);
|
file.setID(fileID);
|
||||||
file.setSEQ(bitstream.getSequenceID());
|
file.setSEQ(bitstream.getSequenceID());
|
||||||
@@ -924,7 +922,7 @@ public abstract class AbstractMETSDisseminator
|
|||||||
* extracted text or a thumbnail, so we use the name to work
|
* extracted text or a thumbnail, so we use the name to work
|
||||||
* out which bitstream to be in the same group as
|
* out which bitstream to be in the same group as
|
||||||
*/
|
*/
|
||||||
String groupID = "GROUP_" + bitstreamIDstart + sid;
|
String groupID = "GROUP_" + bitstreamIDstart + uuid;
|
||||||
if ((bundle.getName() != null)
|
if ((bundle.getName() != null)
|
||||||
&& (bundle.getName().equals("THUMBNAIL") ||
|
&& (bundle.getName().equals("THUMBNAIL") ||
|
||||||
bundle.getName().startsWith("TEXT"))) {
|
bundle.getName().startsWith("TEXT"))) {
|
||||||
@@ -934,7 +932,7 @@ public abstract class AbstractMETSDisseminator
|
|||||||
bitstream);
|
bitstream);
|
||||||
if (original != null) {
|
if (original != null) {
|
||||||
groupID = "GROUP_" + bitstreamIDstart
|
groupID = "GROUP_" + bitstreamIDstart
|
||||||
+ original.getSequenceID();
|
+ String.valueOf(original.getID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file.setGROUPID(groupID);
|
file.setGROUPID(groupID);
|
||||||
@@ -1403,7 +1401,7 @@ public abstract class AbstractMETSDisseminator
|
|||||||
// if bare manifest, use external "persistent" URI for bitstreams
|
// if bare manifest, use external "persistent" URI for bitstreams
|
||||||
if (params != null && (params.getBooleanProperty("manifestOnly", false))) {
|
if (params != null && (params.getBooleanProperty("manifestOnly", false))) {
|
||||||
// Try to build a persistent(-ish) URI for bitstream
|
// Try to build a persistent(-ish) URI for bitstream
|
||||||
// Format: {site-base-url}/bitstream/{item-handle}/{sequence-id}/{bitstream-name}
|
// Format: {site-ui-url}/bitstreams/{bitstream-uuid}
|
||||||
try {
|
try {
|
||||||
// get handle of parent Item of this bitstream, if there is one:
|
// get handle of parent Item of this bitstream, if there is one:
|
||||||
String handle = null;
|
String handle = null;
|
||||||
@@ -1414,26 +1412,13 @@ public abstract class AbstractMETSDisseminator
|
|||||||
handle = bi.get(0).getHandle();
|
handle = bi.get(0).getHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (handle != null) {
|
|
||||||
return configurationService
|
return configurationService
|
||||||
.getProperty("dspace.ui.url")
|
.getProperty("dspace.ui.url")
|
||||||
+ "/bitstream/"
|
+ "/bitstreams/"
|
||||||
+ handle
|
+ String.valueOf(bitstream.getID())
|
||||||
+ "/"
|
+ "/download";
|
||||||
+ String.valueOf(bitstream.getSequenceID())
|
|
||||||
+ "/"
|
|
||||||
+ URLEncoder.encode(bitstream.getName(), "UTF-8");
|
|
||||||
} else { //no Handle assigned, so persistent(-ish) URI for bitstream is
|
|
||||||
// Format: {site-base-url}/retrieve/{bitstream-internal-id}
|
|
||||||
return configurationService
|
|
||||||
.getProperty("dspace.ui.url")
|
|
||||||
+ "/retrieve/"
|
|
||||||
+ String.valueOf(bitstream.getID());
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Database problem", e);
|
log.error("Database problem", e);
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
log.error("Unknown character set", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should only get here if we failed to build a nice URL above
|
// We should only get here if we failed to build a nice URL above
|
||||||
|
@@ -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.ctask.general;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.curate.AbstractCurationTask;
|
||||||
|
import org.dspace.curate.Curator;
|
||||||
|
import org.dspace.identifier.IdentifierException;
|
||||||
|
import org.dspace.identifier.IdentifierProvider;
|
||||||
|
import org.dspace.identifier.VersionedHandleIdentifierProviderWithCanonicalHandles;
|
||||||
|
import org.dspace.identifier.factory.IdentifierServiceFactory;
|
||||||
|
import org.dspace.identifier.service.IdentifierService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that an object has all of the identifiers that it should, minting them
|
||||||
|
* as necessary.
|
||||||
|
*
|
||||||
|
* @author Mark H. Wood {@literal <mwood@iupui.edu>}
|
||||||
|
*/
|
||||||
|
public class CreateMissingIdentifiers
|
||||||
|
extends AbstractCurationTask {
|
||||||
|
private static final Logger LOG = LogManager.getLogger();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int perform(DSpaceObject dso)
|
||||||
|
throws IOException {
|
||||||
|
// Only some kinds of model objects get identifiers
|
||||||
|
if (!(dso instanceof Item)) {
|
||||||
|
return Curator.CURATE_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Temporary escape when an incompatible provider is configured.
|
||||||
|
// XXX Remove this when the provider is fixed.
|
||||||
|
boolean compatible = DSpaceServicesFactory
|
||||||
|
.getInstance()
|
||||||
|
.getServiceManager()
|
||||||
|
.getServiceByName(
|
||||||
|
VersionedHandleIdentifierProviderWithCanonicalHandles.class.getCanonicalName(),
|
||||||
|
IdentifierProvider.class) == null;
|
||||||
|
if (!compatible) {
|
||||||
|
setResult("This task is not compatible with VersionedHandleIdentifierProviderWithCanonicalHandles");
|
||||||
|
return Curator.CURATE_ERROR;
|
||||||
|
}
|
||||||
|
// XXX End of escape
|
||||||
|
|
||||||
|
String typeText = Constants.typeText[dso.getType()];
|
||||||
|
|
||||||
|
// Get a Context
|
||||||
|
Context context;
|
||||||
|
try {
|
||||||
|
context = Curator.curationContext();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
report("Could not get the curation Context: " + ex.getMessage());
|
||||||
|
return Curator.CURATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the IdentifierService implementation
|
||||||
|
IdentifierService identifierService = IdentifierServiceFactory
|
||||||
|
.getInstance()
|
||||||
|
.getIdentifierService();
|
||||||
|
|
||||||
|
// Register any missing identifiers.
|
||||||
|
try {
|
||||||
|
identifierService.register(context, dso);
|
||||||
|
} catch (AuthorizeException | IdentifierException | SQLException ex) {
|
||||||
|
String message = ex.getMessage();
|
||||||
|
report(String.format("Identifier(s) not minted for %s %s: %s%n",
|
||||||
|
typeText, dso.getID().toString(), message));
|
||||||
|
LOG.error("Identifier(s) not minted: {}", message);
|
||||||
|
return Curator.CURATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success!
|
||||||
|
report(String.format("%s %s registered.%n",
|
||||||
|
typeText, dso.getID().toString()));
|
||||||
|
return Curator.CURATE_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
@@ -21,7 +21,6 @@ import org.apache.solr.client.solrj.impl.HttpSolrClient;
|
|||||||
import org.dspace.discovery.indexobject.IndexableItem;
|
import org.dspace.discovery.indexobject.IndexableItem;
|
||||||
import org.dspace.service.impl.HttpConnectionPoolService;
|
import org.dspace.service.impl.HttpConnectionPoolService;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
|
||||||
import org.dspace.storage.rdbms.DatabaseUtils;
|
import org.dspace.storage.rdbms.DatabaseUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
@@ -75,14 +74,13 @@ public class SolrSearchCore {
|
|||||||
*/
|
*/
|
||||||
protected void initSolr() {
|
protected void initSolr() {
|
||||||
if (solr == null) {
|
if (solr == null) {
|
||||||
String solrService = DSpaceServicesFactory.getInstance().getConfigurationService()
|
String solrService = configurationService.getProperty("discovery.search.server");
|
||||||
.getProperty("discovery.search.server");
|
|
||||||
|
|
||||||
UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS);
|
UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS);
|
||||||
if (urlValidator.isValid(solrService) || configurationService
|
if (urlValidator.isValid(solrService) || configurationService
|
||||||
.getBooleanProperty("discovery.solr.url.validation.enabled", true)) {
|
.getBooleanProperty("discovery.solr.url.validation.enabled", true)) {
|
||||||
try {
|
try {
|
||||||
log.debug("Solr URL: " + solrService);
|
log.debug("Solr URL: {}", solrService);
|
||||||
HttpSolrClient solrServer = new HttpSolrClient.Builder(solrService)
|
HttpSolrClient solrServer = new HttpSolrClient.Builder(solrService)
|
||||||
.withHttpClient(httpConnectionPoolService.getClient())
|
.withHttpClient(httpConnectionPoolService.getClient())
|
||||||
.build();
|
.build();
|
||||||
@@ -103,10 +101,13 @@ public class SolrSearchCore {
|
|||||||
|
|
||||||
solr = solrServer;
|
solr = solrServer;
|
||||||
} catch (SolrServerException | IOException e) {
|
} catch (SolrServerException | IOException e) {
|
||||||
log.error("Error while initializing solr server", e);
|
log.error("Error while initializing solr server {}",
|
||||||
|
solrService, e);
|
||||||
|
throw new RuntimeException("Failed to contact Solr at " + solrService
|
||||||
|
+ " : " + e.getMessage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.error("Error while initializing solr, invalid url: " + solrService);
|
log.error("Error while initializing solr, invalid url: {}", solrService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -33,6 +34,7 @@ import org.dspace.content.dto.MetadataValueDTO;
|
|||||||
import org.dspace.external.OpenAIRERestConnector;
|
import org.dspace.external.OpenAIRERestConnector;
|
||||||
import org.dspace.external.model.ExternalDataObject;
|
import org.dspace.external.model.ExternalDataObject;
|
||||||
import org.dspace.external.provider.AbstractExternalDataProvider;
|
import org.dspace.external.provider.AbstractExternalDataProvider;
|
||||||
|
import org.dspace.importer.external.metadatamapping.MetadataFieldConfig;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,13 +42,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
* will deal with the OpenAIRE External Data lookup
|
* will deal with the OpenAIRE External Data lookup
|
||||||
*
|
*
|
||||||
* @author paulo-graca
|
* @author paulo-graca
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
||||||
|
|
||||||
/**
|
|
||||||
* log4j logger
|
|
||||||
*/
|
|
||||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(OpenAIREFundingDataProvider.class);
|
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(OpenAIREFundingDataProvider.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,6 +52,16 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
|||||||
*/
|
*/
|
||||||
protected static final String PREFIX = "info:eu-repo/grantAgreement";
|
protected static final String PREFIX = "info:eu-repo/grantAgreement";
|
||||||
|
|
||||||
|
private static final String TITLE = "dcTitle";
|
||||||
|
private static final String SUBJECT = "dcSubject";
|
||||||
|
private static final String AWARD_URI = "awardURI";
|
||||||
|
private static final String FUNDER_NAME = "funderName";
|
||||||
|
private static final String SPATIAL = "coverageSpatial";
|
||||||
|
private static final String AWARD_NUMBER = "awardNumber";
|
||||||
|
private static final String FUNDER_ID = "funderIdentifier";
|
||||||
|
private static final String FUNDING_STREAM = "fundingStream";
|
||||||
|
private static final String TITLE_ALTERNATIVE = "titleAlternative";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rows default limit
|
* rows default limit
|
||||||
*/
|
*/
|
||||||
@@ -69,11 +77,9 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
|||||||
*/
|
*/
|
||||||
protected OpenAIRERestConnector connector;
|
protected OpenAIRERestConnector connector;
|
||||||
|
|
||||||
/**
|
protected Map<String, MetadataFieldConfig> metadataFields;
|
||||||
* required method
|
|
||||||
*/
|
public void init() throws IOException {}
|
||||||
public void init() throws IOException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSourceIdentifier() {
|
public String getSourceIdentifier() {
|
||||||
@@ -266,14 +272,22 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, MetadataFieldConfig> getMetadataFields() {
|
||||||
|
return metadataFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadataFields(Map<String, MetadataFieldConfig> metadataFields) {
|
||||||
|
this.metadataFields = metadataFields;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenAIRE Funding External Data Builder Class
|
* OpenAIRE Funding External Data Builder Class
|
||||||
*
|
*
|
||||||
* @author pgraca
|
* @author pgraca
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static class ExternalDataObjectBuilder {
|
public class ExternalDataObjectBuilder {
|
||||||
ExternalDataObject externalDataObject;
|
|
||||||
|
private ExternalDataObject externalDataObject;
|
||||||
|
|
||||||
public ExternalDataObjectBuilder(Project project) {
|
public ExternalDataObjectBuilder(Project project) {
|
||||||
String funderIdPrefix = "urn:openaire:";
|
String funderIdPrefix = "urn:openaire:";
|
||||||
@@ -283,46 +297,42 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
|||||||
for (FundingTreeType fundingTree : projectHelper.getFundingTreeTypes()) {
|
for (FundingTreeType fundingTree : projectHelper.getFundingTreeTypes()) {
|
||||||
FunderType funder = fundingTree.getFunder();
|
FunderType funder = fundingTree.getFunder();
|
||||||
// Funder name
|
// Funder name
|
||||||
this.addFunderName(funder.getName());
|
this.addMetadata(metadataFields.get(FUNDER_NAME), funder.getName());
|
||||||
// Funder Id - convert it to an urn
|
// Funder Id - convert it to an urn
|
||||||
this.addFunderID(funderIdPrefix + funder.getId());
|
this.addMetadata(metadataFields.get(FUNDER_ID), funderIdPrefix + funder.getId());
|
||||||
// Jurisdiction
|
// Jurisdiction
|
||||||
this.addFunderJuristiction(funder.getJurisdiction());
|
this.addMetadata(metadataFields.get(SPATIAL), funder.getJurisdiction());
|
||||||
|
|
||||||
FundingHelper fundingHelper = new FundingHelper(
|
FundingHelper fundingHelper = new FundingHelper(
|
||||||
fundingTree.getFundingLevel2OrFundingLevel1OrFundingLevel0());
|
fundingTree.getFundingLevel2OrFundingLevel1OrFundingLevel0());
|
||||||
|
|
||||||
// Funding description
|
// Funding description
|
||||||
for (FundingType funding : fundingHelper.getFirstAvailableFunding()) {
|
for (FundingType funding : fundingHelper.getFirstAvailableFunding()) {
|
||||||
this.addFundingStream(funding.getDescription());
|
this.addMetadata(metadataFields.get(FUNDING_STREAM), funding.getDescription());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
for (String title : projectHelper.getTitles()) {
|
for (String title : projectHelper.getTitles()) {
|
||||||
this.addAwardTitle(title);
|
this.addMetadata(metadataFields.get(TITLE), title);
|
||||||
this.setDisplayValue(title);
|
this.setDisplayValue(title);
|
||||||
this.setValue(title);
|
this.setValue(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Code
|
// Code
|
||||||
for (String code : projectHelper.getCodes()) {
|
for (String code : projectHelper.getCodes()) {
|
||||||
this.addAwardNumber(code);
|
this.addMetadata(metadataFields.get(AWARD_NUMBER), code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Website url
|
// Website url
|
||||||
for (String url : projectHelper.getWebsiteUrls()) {
|
for (String url : projectHelper.getWebsiteUrls()) {
|
||||||
this.addAwardURI(url);
|
this.addMetadata(metadataFields.get(AWARD_URI), url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acronyms
|
// Acronyms
|
||||||
for (String acronym : projectHelper.getAcronyms()) {
|
for (String acronym : projectHelper.getAcronyms()) {
|
||||||
this.addFundingItemAcronym(acronym);
|
this.addMetadata(metadataFields.get(TITLE_ALTERNATIVE), acronym);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keywords
|
// Keywords
|
||||||
for (String keyword : projectHelper.getKeywords()) {
|
for (String keyword : projectHelper.getKeywords()) {
|
||||||
this.addSubject(keyword);
|
this.addMetadata(metadataFields.get(SUBJECT), keyword);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +376,6 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
|||||||
* @return ExternalDataObjectBuilder
|
* @return ExternalDataObjectBuilder
|
||||||
*/
|
*/
|
||||||
public ExternalDataObjectBuilder setId(String id) {
|
public ExternalDataObjectBuilder setId(String id) {
|
||||||
|
|
||||||
// we use base64 encoding in order to use slashes / and other
|
// we use base64 encoding in order to use slashes / and other
|
||||||
// characters that must be escaped for the <:entry-id>
|
// characters that must be escaped for the <:entry-id>
|
||||||
String base64Id = Base64.getEncoder().encodeToString(id.getBytes());
|
String base64Id = Base64.getEncoder().encodeToString(id.getBytes());
|
||||||
@@ -374,128 +383,10 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public ExternalDataObjectBuilder addMetadata(MetadataFieldConfig metadataField, String value) {
|
||||||
* Add metadata dc.identifier
|
this.externalDataObject.addMetadata(new MetadataValueDTO(metadataField.getSchema(),
|
||||||
*
|
metadataField.getElement(),
|
||||||
* @param metadata identifier
|
metadataField.getQualifier(), null, value));
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addIdentifier(String identifier) {
|
|
||||||
this.externalDataObject.addMetadata(new MetadataValueDTO("dc", "identifier", null, null, identifier));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata project.funder.name
|
|
||||||
*
|
|
||||||
* @param metadata funderName
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addFunderName(String funderName) {
|
|
||||||
this.externalDataObject.addMetadata(new MetadataValueDTO("project", "funder", "name", null, funderName));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata project.funder.identifier
|
|
||||||
*
|
|
||||||
* @param metadata funderId
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addFunderID(String funderID) {
|
|
||||||
this.externalDataObject
|
|
||||||
.addMetadata(new MetadataValueDTO("project", "funder", "identifier", null, funderID));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata dc.title
|
|
||||||
*
|
|
||||||
* @param metadata awardTitle
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addAwardTitle(String awardTitle) {
|
|
||||||
this.externalDataObject.addMetadata(new MetadataValueDTO("dc", "title", null, null, awardTitle));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata oaire.fundingStream
|
|
||||||
*
|
|
||||||
* @param metadata fundingStream
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addFundingStream(String fundingStream) {
|
|
||||||
this.externalDataObject
|
|
||||||
.addMetadata(new MetadataValueDTO("oaire", "fundingStream", null, null, fundingStream));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata oaire.awardNumber
|
|
||||||
*
|
|
||||||
* @param metadata awardNumber
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addAwardNumber(String awardNumber) {
|
|
||||||
this.externalDataObject.addMetadata(new MetadataValueDTO("oaire", "awardNumber", null, null, awardNumber));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata oaire.awardURI
|
|
||||||
*
|
|
||||||
* @param metadata websiteUrl
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addAwardURI(String websiteUrl) {
|
|
||||||
this.externalDataObject.addMetadata(new MetadataValueDTO("oaire", "awardURI", null, null, websiteUrl));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata dc.title.alternative
|
|
||||||
*
|
|
||||||
* @param metadata fundingItemAcronym
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addFundingItemAcronym(String fundingItemAcronym) {
|
|
||||||
this.externalDataObject
|
|
||||||
.addMetadata(new MetadataValueDTO("dc", "title", "alternative", null, fundingItemAcronym));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata dc.coverage.spatial
|
|
||||||
*
|
|
||||||
* @param metadata funderJuristiction
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addFunderJuristiction(String funderJuristiction) {
|
|
||||||
this.externalDataObject
|
|
||||||
.addMetadata(new MetadataValueDTO("dc", "coverage", "spatial", null, funderJuristiction));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata dc.description
|
|
||||||
*
|
|
||||||
* @param metadata description
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addDescription(String description) {
|
|
||||||
this.externalDataObject.addMetadata(new MetadataValueDTO("dc", "description", null, null, description));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add metadata dc.subject
|
|
||||||
*
|
|
||||||
* @param metadata subject
|
|
||||||
* @return ExternalDataObjectBuilder
|
|
||||||
*/
|
|
||||||
public ExternalDataObjectBuilder addSubject(String subject) {
|
|
||||||
this.externalDataObject.addMetadata(new MetadataValueDTO("dc", "subject", null, null, subject));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,4 +399,5 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider {
|
|||||||
return this.externalDataObject;
|
return this.externalDataObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -19,10 +19,8 @@ import java.util.Calendar;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
|
||||||
import ORG.oclc.oai.harvester2.verb.Identify;
|
|
||||||
import ORG.oclc.oai.harvester2.verb.ListIdentifiers;
|
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.harvest.dao.HarvestedCollectionDAO;
|
import org.dspace.harvest.dao.HarvestedCollectionDAO;
|
||||||
@@ -33,6 +31,8 @@ import org.jdom2.Document;
|
|||||||
import org.jdom2.Element;
|
import org.jdom2.Element;
|
||||||
import org.jdom2.Namespace;
|
import org.jdom2.Namespace;
|
||||||
import org.jdom2.input.DOMBuilder;
|
import org.jdom2.input.DOMBuilder;
|
||||||
|
import org.oclc.oai.harvester2.verb.Identify;
|
||||||
|
import org.oclc.oai.harvester2.verb.ListIdentifiers;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.w3c.dom.DOMException;
|
import org.w3c.dom.DOMException;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
@@ -198,7 +198,7 @@ public class HarvestedCollectionServiceImpl implements HarvestedCollectionServic
|
|||||||
// First, see if we can contact the target server at all.
|
// First, see if we can contact the target server at all.
|
||||||
try {
|
try {
|
||||||
new Identify(oaiSource);
|
new Identify(oaiSource);
|
||||||
} catch (IOException | ParserConfigurationException | TransformerException | SAXException ex) {
|
} catch (IOException | ParserConfigurationException | XPathExpressionException | SAXException ex) {
|
||||||
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached.");
|
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached.");
|
||||||
return errorSet;
|
return errorSet;
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ public class HarvestedCollectionServiceImpl implements HarvestedCollectionServic
|
|||||||
try {
|
try {
|
||||||
OREOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, OAIHarvester.getORENamespace().getURI());
|
OREOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, OAIHarvester.getORENamespace().getURI());
|
||||||
DMDOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, DMD_NS.getURI());
|
DMDOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, DMD_NS.getURI());
|
||||||
} catch (IOException | ParserConfigurationException | TransformerException | SAXException ex) {
|
} catch (IOException | ParserConfigurationException | XPathExpressionException | SAXException ex) {
|
||||||
errorSet.add(OAI_ADDRESS_ERROR
|
errorSet.add(OAI_ADDRESS_ERROR
|
||||||
+ ": OAI did not respond to ListMetadataFormats query ("
|
+ ": OAI did not respond to ListMetadataFormats query ("
|
||||||
+ ORE_NS.getPrefix() + ":" + OREOAIPrefix + " ; "
|
+ ORE_NS.getPrefix() + ":" + OREOAIPrefix + " ; "
|
||||||
@@ -260,7 +260,8 @@ public class HarvestedCollectionServiceImpl implements HarvestedCollectionServic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | ParserConfigurationException | TransformerException | DOMException | SAXException e) {
|
} catch (IOException | ParserConfigurationException | XPathExpressionException | DOMException |
|
||||||
|
SAXException e) {
|
||||||
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached");
|
errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached");
|
||||||
return errorSet;
|
return errorSet;
|
||||||
} catch (RuntimeException re) {
|
} catch (RuntimeException re) {
|
||||||
|
@@ -28,12 +28,8 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
|
||||||
import ORG.oclc.oai.harvester2.verb.GetRecord;
|
|
||||||
import ORG.oclc.oai.harvester2.verb.Identify;
|
|
||||||
import ORG.oclc.oai.harvester2.verb.ListMetadataFormats;
|
|
||||||
import ORG.oclc.oai.harvester2.verb.ListRecords;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -76,6 +72,10 @@ import org.jdom2.Element;
|
|||||||
import org.jdom2.Namespace;
|
import org.jdom2.Namespace;
|
||||||
import org.jdom2.input.DOMBuilder;
|
import org.jdom2.input.DOMBuilder;
|
||||||
import org.jdom2.output.XMLOutputter;
|
import org.jdom2.output.XMLOutputter;
|
||||||
|
import org.oclc.oai.harvester2.verb.GetRecord;
|
||||||
|
import org.oclc.oai.harvester2.verb.Identify;
|
||||||
|
import org.oclc.oai.harvester2.verb.ListMetadataFormats;
|
||||||
|
import org.oclc.oai.harvester2.verb.ListRecords;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
|
||||||
@@ -493,11 +493,11 @@ public class OAIHarvester {
|
|||||||
* @throws HarvestingException if harvesting error
|
* @throws HarvestingException if harvesting error
|
||||||
* @throws ParserConfigurationException XML parsing error
|
* @throws ParserConfigurationException XML parsing error
|
||||||
* @throws SAXException if XML processing error
|
* @throws SAXException if XML processing error
|
||||||
* @throws TransformerException if XML transformer error
|
* @throws XPathExpressionException if XPath error
|
||||||
*/
|
*/
|
||||||
protected void processRecord(Element record, String OREPrefix, final long currentRecord, long totalListSize)
|
protected void processRecord(Element record, String OREPrefix, final long currentRecord, long totalListSize)
|
||||||
throws SQLException, AuthorizeException, IOException, CrosswalkException, HarvestingException,
|
throws SQLException, AuthorizeException, IOException, CrosswalkException, HarvestingException,
|
||||||
ParserConfigurationException, SAXException, TransformerException {
|
ParserConfigurationException, SAXException, XPathExpressionException {
|
||||||
WorkspaceItem wi = null;
|
WorkspaceItem wi = null;
|
||||||
Date timeStart = new Date();
|
Date timeStart = new Date();
|
||||||
|
|
||||||
@@ -769,10 +769,10 @@ public class OAIHarvester {
|
|||||||
* @throws IOException if IO error
|
* @throws IOException if IO error
|
||||||
* @throws SAXException if XML processing error
|
* @throws SAXException if XML processing error
|
||||||
* @throws ParserConfigurationException XML parsing error
|
* @throws ParserConfigurationException XML parsing error
|
||||||
* @throws TransformerException if XML transformer error
|
* @throws XPathExpressionException if XPath error
|
||||||
*/
|
*/
|
||||||
private String oaiGetDateGranularity(String oaiSource)
|
private String oaiGetDateGranularity(String oaiSource)
|
||||||
throws IOException, ParserConfigurationException, SAXException, TransformerException {
|
throws IOException, ParserConfigurationException, SAXException, XPathExpressionException {
|
||||||
Identify iden = new Identify(oaiSource);
|
Identify iden = new Identify(oaiSource);
|
||||||
return iden.getDocument().getElementsByTagNameNS(OAI_NS.getURI(), "granularity").item(0).getTextContent();
|
return iden.getDocument().getElementsByTagNameNS(OAI_NS.getURI(), "granularity").item(0).getTextContent();
|
||||||
}
|
}
|
||||||
@@ -789,11 +789,11 @@ public class OAIHarvester {
|
|||||||
* operations.
|
* operations.
|
||||||
* @throws ParserConfigurationException XML parsing error
|
* @throws ParserConfigurationException XML parsing error
|
||||||
* @throws SAXException if XML processing error
|
* @throws SAXException if XML processing error
|
||||||
* @throws TransformerException if XML transformer error
|
* @throws XPathExpressionException if XPath error
|
||||||
* @throws ConnectException if could not connect to OAI server
|
* @throws ConnectException if could not connect to OAI server
|
||||||
*/
|
*/
|
||||||
public static String oaiResolveNamespaceToPrefix(String oaiSource, String MDNamespace)
|
public static String oaiResolveNamespaceToPrefix(String oaiSource, String MDNamespace)
|
||||||
throws IOException, ParserConfigurationException, SAXException, TransformerException, ConnectException {
|
throws IOException, ParserConfigurationException, SAXException, XPathExpressionException, ConnectException {
|
||||||
String metaPrefix = null;
|
String metaPrefix = null;
|
||||||
|
|
||||||
// Query the OAI server for the metadata
|
// Query the OAI server for the metadata
|
||||||
@@ -866,11 +866,11 @@ public class OAIHarvester {
|
|||||||
* operations.
|
* operations.
|
||||||
* @throws ParserConfigurationException XML parsing error
|
* @throws ParserConfigurationException XML parsing error
|
||||||
* @throws SAXException if XML processing error
|
* @throws SAXException if XML processing error
|
||||||
* @throws TransformerException if XML transformer error
|
* @throws XPathExpressionException if XPath error
|
||||||
* @throws HarvestingException if harvesting error
|
* @throws HarvestingException if harvesting error
|
||||||
*/
|
*/
|
||||||
protected List<Element> getMDrecord(String oaiSource, String itemOaiId, String metadataPrefix)
|
protected List<Element> getMDrecord(String oaiSource, String itemOaiId, String metadataPrefix)
|
||||||
throws IOException, ParserConfigurationException, SAXException, TransformerException, HarvestingException {
|
throws IOException, ParserConfigurationException, SAXException, XPathExpressionException, HarvestingException {
|
||||||
GetRecord getRecord = new GetRecord(oaiSource, itemOaiId, metadataPrefix);
|
GetRecord getRecord = new GetRecord(oaiSource, itemOaiId, metadataPrefix);
|
||||||
Set<String> errorSet = new HashSet<>();
|
Set<String> errorSet = new HashSet<>();
|
||||||
// If the metadata is not available for this item, can the whole thing
|
// If the metadata is not available for this item, can the whole thing
|
||||||
|
@@ -92,6 +92,9 @@ public interface IdentifierService {
|
|||||||
throws AuthorizeException, SQLException, IdentifierException;
|
throws AuthorizeException, SQLException, IdentifierException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Used to register newly-minted identifiers. Each provider is responsible
|
||||||
|
* for creating the appropriate identifier. All providers are interrogated.
|
||||||
|
*
|
||||||
* @param context The relevant DSpace Context.
|
* @param context The relevant DSpace Context.
|
||||||
* @param dso DSpace object to be registered
|
* @param dso DSpace object to be registered
|
||||||
* @throws AuthorizeException if authorization error
|
* @throws AuthorizeException if authorization error
|
||||||
@@ -101,7 +104,7 @@ public interface IdentifierService {
|
|||||||
void register(Context context, DSpaceObject dso) throws AuthorizeException, SQLException, IdentifierException;
|
void register(Context context, DSpaceObject dso) 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
|
||||||
* identifier. All Providers are interrogated. Multiple providers
|
* identifier. All Providers are interrogated. Multiple providers
|
||||||
* can process the same identifier.
|
* can process the same identifier.
|
||||||
|
@@ -70,11 +70,24 @@ public class BibtexImportMetadataSourceServiceImpl extends AbstractPlainMetadata
|
|||||||
keyValueItem.setKey(entry.getValue().getType().getValue());
|
keyValueItem.setKey(entry.getValue().getType().getValue());
|
||||||
keyValueItem.setValue(entry.getKey().getValue());
|
keyValueItem.setValue(entry.getKey().getValue());
|
||||||
keyValues.add(keyValueItem);
|
keyValues.add(keyValueItem);
|
||||||
|
PlainMetadataKeyValueItem typeItem = new PlainMetadataKeyValueItem();
|
||||||
|
typeItem.setKey("type");
|
||||||
|
typeItem.setValue(entry.getValue().getType().getValue());
|
||||||
|
keyValues.add(typeItem);
|
||||||
if (entry.getValue().getFields() != null) {
|
if (entry.getValue().getFields() != null) {
|
||||||
for (Entry<Key,Value> subentry : entry.getValue().getFields().entrySet()) {
|
for (Entry<Key,Value> subentry : entry.getValue().getFields().entrySet()) {
|
||||||
PlainMetadataKeyValueItem innerItem = new PlainMetadataKeyValueItem();
|
PlainMetadataKeyValueItem innerItem = new PlainMetadataKeyValueItem();
|
||||||
innerItem.setKey(subentry.getKey().getValue());
|
innerItem.setKey(subentry.getKey().getValue().toLowerCase());
|
||||||
innerItem.setValue(subentry.getValue().toUserString());
|
String latexString = subentry.getValue().toUserString();
|
||||||
|
try {
|
||||||
|
org.jbibtex.LaTeXParser laTeXParser = new org.jbibtex.LaTeXParser();
|
||||||
|
List<org.jbibtex.LaTeXObject> latexObjects = laTeXParser.parse(latexString);
|
||||||
|
org.jbibtex.LaTeXPrinter laTeXPrinter = new org.jbibtex.LaTeXPrinter();
|
||||||
|
String plainTextString = laTeXPrinter.print(latexObjects);
|
||||||
|
innerItem.setValue(plainTextString.replaceAll("\n", " "));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
innerItem.setValue(latexString);
|
||||||
|
}
|
||||||
keyValues.add(innerItem);
|
keyValues.add(innerItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* 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.importer.external.metadatamapping.contributor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.dspace.importer.external.metadatamapping.MetadataFieldMapping;
|
||||||
|
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class used to split another MetadataContributor's output into distinct values.
|
||||||
|
* The split is performed by matching a regular expression against the wrapped MetadataContributor's output.
|
||||||
|
*
|
||||||
|
* @author Philipp Rumpf (philipp.rumpf@uni-bamberg.de)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SplitMetadataContributor<T> implements MetadataContributor<T> {
|
||||||
|
private final MetadataContributor<T> innerContributor;
|
||||||
|
private final String regex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param innerContributor The MetadataContributor whose output is split
|
||||||
|
* @param regex A regular expression matching the separator between different values
|
||||||
|
*/
|
||||||
|
public SplitMetadataContributor(MetadataContributor<T> innerContributor, String regex) {
|
||||||
|
this.innerContributor = innerContributor;
|
||||||
|
this.regex = regex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMetadataFieldMapping(MetadataFieldMapping<T, MetadataContributor<T>> rt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each metadatum returned by the wrapped MetadataContributor is split into one or more metadata values
|
||||||
|
* based on the provided regular expression.
|
||||||
|
*
|
||||||
|
* @param t The recordType object to retrieve metadata from
|
||||||
|
* @return The collection of processed metadata values
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Collection<MetadatumDTO> contributeMetadata(T t) {
|
||||||
|
Collection<MetadatumDTO> metadata = innerContributor.contributeMetadata(t);
|
||||||
|
ArrayList<MetadatumDTO> splitMetadata = new ArrayList<>();
|
||||||
|
for (MetadatumDTO metadatumDTO : metadata) {
|
||||||
|
String[] split = metadatumDTO.getValue().split(regex);
|
||||||
|
for (String splitItem : split) {
|
||||||
|
MetadatumDTO splitMetadatumDTO = new MetadatumDTO();
|
||||||
|
splitMetadatumDTO.setSchema(metadatumDTO.getSchema());
|
||||||
|
splitMetadatumDTO.setElement(metadatumDTO.getElement());
|
||||||
|
splitMetadatumDTO.setQualifier(metadatumDTO.getQualifier());
|
||||||
|
splitMetadatumDTO.setValue(splitItem);
|
||||||
|
splitMetadata.add(splitMetadatumDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return splitMetadata;
|
||||||
|
}
|
||||||
|
}
|
@@ -621,6 +621,10 @@ public class StatisticsDataVisits extends StatisticsData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dsoId != null && query.dsoType != -1) {
|
if (dsoId != null && query.dsoType != -1) {
|
||||||
|
// Store the UUID of the DSO as an attribute. Needed in particular for Bitstream download usage reports,
|
||||||
|
// as the Bitstream itself won't be available when converting points to their REST representation
|
||||||
|
attrs.put("id", dsoId);
|
||||||
|
|
||||||
switch (query.dsoType) {
|
switch (query.dsoType) {
|
||||||
case Constants.BITSTREAM:
|
case Constants.BITSTREAM:
|
||||||
Bitstream bit = bitstreamService.findByIdOrLegacyId(context, dsoId);
|
Bitstream bit = bitstreamService.findByIdOrLegacyId(context, dsoId);
|
||||||
|
@@ -8,15 +8,17 @@
|
|||||||
package org.dspace.submit.model;
|
package org.dspace.submit.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A collection of conditions to be met when uploading Bitstreams.
|
||||||
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
|
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
|
||||||
*/
|
*/
|
||||||
public class UploadConfiguration {
|
public class UploadConfiguration {
|
||||||
|
|
||||||
private ConfigurationService configurationService;
|
private final ConfigurationService configurationService;
|
||||||
|
|
||||||
private String metadataDefinition;
|
private String metadataDefinition;
|
||||||
private List<AccessConditionOption> options;
|
private List<AccessConditionOption> options;
|
||||||
@@ -24,22 +26,52 @@ public class UploadConfiguration {
|
|||||||
private Boolean required;
|
private Boolean required;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a bitstream uploading configuration.
|
||||||
|
* @param configurationService DSpace configuration provided by the DI container.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public UploadConfiguration(ConfigurationService configurationService) {
|
||||||
|
this.configurationService = configurationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of access restriction types from which a submitter may choose.
|
||||||
|
* @return choices for restricting access to Bitstreams.
|
||||||
|
*/
|
||||||
public List<AccessConditionOption> getOptions() {
|
public List<AccessConditionOption> getOptions() {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the list of access restriction types from which to choose.
|
||||||
|
* Required. May be empty.
|
||||||
|
* @param options choices for restricting access to Bitstreams.
|
||||||
|
*/
|
||||||
public void setOptions(List<AccessConditionOption> options) {
|
public void setOptions(List<AccessConditionOption> options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the submission form to which these conditions are attached.
|
||||||
|
* @return the form's name.
|
||||||
|
*/
|
||||||
public String getMetadata() {
|
public String getMetadata() {
|
||||||
return metadataDefinition;
|
return metadataDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name the submission form to which these conditions are attached.
|
||||||
|
* @param metadata the form's name.
|
||||||
|
*/
|
||||||
public void setMetadata(String metadata) {
|
public void setMetadata(String metadata) {
|
||||||
this.metadataDefinition = metadata;
|
this.metadataDefinition = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit on the maximum size of an uploaded Bitstream.
|
||||||
|
* @return maximum upload size in bytes.
|
||||||
|
*/
|
||||||
public Long getMaxSize() {
|
public Long getMaxSize() {
|
||||||
if (maxSize == null) {
|
if (maxSize == null) {
|
||||||
maxSize = configurationService.getLongProperty("upload.max");
|
maxSize = configurationService.getLongProperty("upload.max");
|
||||||
@@ -47,10 +79,18 @@ public class UploadConfiguration {
|
|||||||
return maxSize;
|
return maxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit the maximum size of an uploaded Bitstream.
|
||||||
|
* @param maxSize maximum upload size in bytes.
|
||||||
|
*/
|
||||||
public void setMaxSize(Long maxSize) {
|
public void setMaxSize(Long maxSize) {
|
||||||
this.maxSize = maxSize;
|
this.maxSize = maxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is at least one Bitstream required when submitting a new Item?
|
||||||
|
* @return true if a Bitstream is required.
|
||||||
|
*/
|
||||||
public Boolean isRequired() {
|
public Boolean isRequired() {
|
||||||
if (required == null) {
|
if (required == null) {
|
||||||
//defaults to true
|
//defaults to true
|
||||||
@@ -60,25 +100,27 @@ public class UploadConfiguration {
|
|||||||
return required;
|
return required;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is at least one Bitstream required when submitting a new Item?
|
||||||
|
* @param required true if a Bitstream is required.
|
||||||
|
*/
|
||||||
public void setRequired(Boolean required) {
|
public void setRequired(Boolean required) {
|
||||||
this.required = required;
|
this.required = required;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationService getConfigurationService() {
|
/**
|
||||||
return configurationService;
|
* The unique name of this configuration.
|
||||||
}
|
* @return configuration's name.
|
||||||
|
*/
|
||||||
public void setConfigurationService(ConfigurationService configurationService) {
|
|
||||||
this.configurationService = configurationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give this configuration a unique name. Required.
|
||||||
|
* @param name configuration's name.
|
||||||
|
*/
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -5,8 +5,7 @@
|
|||||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||||
|
|
||||||
<bean id="uploadConfigurationDefault" class="org.dspace.submit.model.UploadConfiguration">
|
<bean id="uploadConfigurationDefault" class="org.dspace.submit.model.UploadConfiguration">
|
||||||
<property name="name" value="upload"></property>
|
<property name="name" value="upload"/>
|
||||||
<property name="configurationService" ref="org.dspace.services.ConfigurationService"/>
|
|
||||||
<property name="metadata" value="bitstream-metadata" />
|
<property name="metadata" value="bitstream-metadata" />
|
||||||
<property name="options">
|
<property name="options">
|
||||||
<list>
|
<list>
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:util="http://www.springframework.org/schema/util"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/util
|
||||||
|
http://www.springframework.org/schema/util/spring-util.xsd"
|
||||||
default-lazy-init="true">
|
default-lazy-init="true">
|
||||||
|
|
||||||
<bean id="mockOpenAIRERestConnector" class="org.dspace.external.MockOpenAIRERestConnector">
|
<bean id="mockOpenAIRERestConnector" class="org.dspace.external.MockOpenAIRERestConnector">
|
||||||
@@ -15,6 +19,7 @@
|
|||||||
init-method="init">
|
init-method="init">
|
||||||
<property name="sourceIdentifier" value="openAIREFunding" />
|
<property name="sourceIdentifier" value="openAIREFunding" />
|
||||||
<property name="connector" ref="mockOpenAIRERestConnector" />
|
<property name="connector" ref="mockOpenAIRERestConnector" />
|
||||||
|
<property name="metadataFields" ref="mapOfmetadata"/>
|
||||||
<property name="supportedEntityTypes">
|
<property name="supportedEntityTypes">
|
||||||
<list>
|
<list>
|
||||||
<value>Project</value>
|
<value>Project</value>
|
||||||
@@ -22,4 +27,63 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<util:map id="mapOfmetadata"
|
||||||
|
map-class="java.util.HashMap" key-type="java.lang.String" value-type="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<entry key="awardNumber" value-ref="openaireAwardNumber" />
|
||||||
|
<entry key="fundingStream" value-ref="openaireFundingStream" />
|
||||||
|
<entry key="awardURI" value-ref="openaireAwardURI" />
|
||||||
|
<entry key="funderName" value-ref="openaireFunderName" />
|
||||||
|
<entry key="funderIdentifier" value-ref="openaireFunderIdentifier" />
|
||||||
|
<entry key="dcTitle" value-ref="openaireTitle" />
|
||||||
|
<entry key="titleAlternative" value-ref="openaireTitleAlternative" />
|
||||||
|
<entry key="dcIdentifier" value-ref="openaireIdentifier" />
|
||||||
|
<entry key="coverageSpatial" value-ref="openaireSpatial" />
|
||||||
|
<entry key="dcDescription" value-ref="openaireDescription" />
|
||||||
|
<entry key="dcSubject" value-ref="openaireSubject" />
|
||||||
|
</util:map>
|
||||||
|
|
||||||
|
<bean id="openaireAwardNumber" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="oaire.awardNumber"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireFundingStream" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="oaire.fundingStream"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireAwardURI" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="oaire.awardURI"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireFunderName" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="project.funder.name"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireFunderIdentifier" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="project.funder.identifier"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireTitle" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.title"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireTitleAlternative" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.title.alternative"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireIdentifier" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.identifier"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireSpatial" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.coverage.spatial"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireDescription" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.description"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireSubject" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.subject"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* 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 static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
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.dspace.eperson.Group;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Mark H. Wood <mwood@iupui.edu>
|
||||||
|
*/
|
||||||
|
public class CollectionAdministratorsRequestItemStrategyTest {
|
||||||
|
private static final String NAME = "John Q. Public";
|
||||||
|
private static final String EMAIL = "jqpublic@example.com";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getRequestItemAuthor method, of class CollectionAdministratorsRequestItemStrategy.
|
||||||
|
* @throws java.lang.Exception passed through.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetRequestItemAuthor()
|
||||||
|
throws Exception {
|
||||||
|
System.out.println("getRequestItemAuthor");
|
||||||
|
|
||||||
|
Context context = Mockito.mock(Context.class);
|
||||||
|
|
||||||
|
EPerson eperson1 = Mockito.mock(EPerson.class);
|
||||||
|
Mockito.when(eperson1.getEmail()).thenReturn(EMAIL);
|
||||||
|
Mockito.when(eperson1.getFullName()).thenReturn(NAME);
|
||||||
|
|
||||||
|
Group group1 = Mockito.mock(Group.class);
|
||||||
|
Mockito.when(group1.getMembers()).thenReturn(List.of(eperson1));
|
||||||
|
|
||||||
|
Collection collection1 = Mockito.mock(Collection.class);
|
||||||
|
Mockito.when(collection1.getAdministrators()).thenReturn(group1);
|
||||||
|
|
||||||
|
Item item = Mockito.mock(Item.class);
|
||||||
|
Mockito.when(item.getOwningCollection()).thenReturn(collection1);
|
||||||
|
Mockito.when(item.getSubmitter()).thenReturn(eperson1);
|
||||||
|
|
||||||
|
CollectionAdministratorsRequestItemStrategy instance = new CollectionAdministratorsRequestItemStrategy();
|
||||||
|
List<RequestItemAuthor> result = instance.getRequestItemAuthor(context,
|
||||||
|
item);
|
||||||
|
assertEquals("Should be one author", 1, result.size());
|
||||||
|
assertEquals("Name should match " + NAME, NAME, result.get(0).getFullName());
|
||||||
|
assertEquals("Email should match " + EMAIL, EMAIL, result.get(0).getEmail());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* 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 static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Mark H. Wood <mwood@iupui.edu>
|
||||||
|
*/
|
||||||
|
public class CombiningRequestItemStrategyTest {
|
||||||
|
/**
|
||||||
|
* Test of getRequestItemAuthor method, of class CombiningRequestItemStrategy.
|
||||||
|
* @throws java.lang.Exception passed through.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetRequestItemAuthor()
|
||||||
|
throws Exception {
|
||||||
|
System.out.println("getRequestItemAuthor");
|
||||||
|
Context context = null;
|
||||||
|
|
||||||
|
Item item = Mockito.mock(Item.class);
|
||||||
|
RequestItemAuthor author1 = new RequestItemAuthor("Pat Paulsen", "ppaulsen@example.com");
|
||||||
|
RequestItemAuthor author2 = new RequestItemAuthor("Alfred E. Neuman", "aeneuman@example.com");
|
||||||
|
RequestItemAuthor author3 = new RequestItemAuthor("Alias Undercover", "aundercover@example.com");
|
||||||
|
|
||||||
|
RequestItemAuthorExtractor strategy1 = Mockito.mock(RequestItemHelpdeskStrategy.class);
|
||||||
|
Mockito.when(strategy1.getRequestItemAuthor(context, item)).thenReturn(List.of(author1));
|
||||||
|
|
||||||
|
RequestItemAuthorExtractor strategy2 = Mockito.mock(RequestItemMetadataStrategy.class);
|
||||||
|
Mockito.when(strategy2.getRequestItemAuthor(context, item)).thenReturn(List.of(author2, author3));
|
||||||
|
|
||||||
|
List<RequestItemAuthorExtractor> strategies = List.of(strategy1, strategy2);
|
||||||
|
|
||||||
|
CombiningRequestItemStrategy instance = new CombiningRequestItemStrategy(strategies);
|
||||||
|
List<RequestItemAuthor> result = instance.getRequestItemAuthor(context,
|
||||||
|
item);
|
||||||
|
assertThat(result, containsInAnyOrder(author1, author2, author3));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* 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.ctask.general;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.ItemBuilder;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.curate.Curator;
|
||||||
|
import org.dspace.identifier.VersionedHandleIdentifierProviderWithCanonicalHandles;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rudimentary test of the curation task.
|
||||||
|
*
|
||||||
|
* @author mwood
|
||||||
|
*/
|
||||||
|
public class CreateMissingIdentifiersIT
|
||||||
|
extends AbstractIntegrationTestWithDatabase {
|
||||||
|
private static final String P_TASK_DEF
|
||||||
|
= "plugin.named.org.dspace.curate.CurationTask";
|
||||||
|
private static final String TASK_NAME = "test";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPerform()
|
||||||
|
throws IOException {
|
||||||
|
ConfigurationService configurationService
|
||||||
|
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
configurationService.setProperty(P_TASK_DEF, null);
|
||||||
|
configurationService.addPropertyValue(P_TASK_DEF,
|
||||||
|
CreateMissingIdentifiers.class.getCanonicalName() + " = " + TASK_NAME);
|
||||||
|
|
||||||
|
Curator curator = new Curator();
|
||||||
|
curator.addTask(TASK_NAME);
|
||||||
|
|
||||||
|
context.setCurrentUser(admin);
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.build();
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.build();
|
||||||
|
Item item = ItemBuilder.createItem(context, collection)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curate with regular test configuration -- should succeed.
|
||||||
|
*/
|
||||||
|
curator.curate(context, item);
|
||||||
|
int status = curator.getStatus(TASK_NAME);
|
||||||
|
assertEquals("Curation should succeed", Curator.CURATE_SUCCESS, status);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now install an incompatible provider to make the task fail.
|
||||||
|
*/
|
||||||
|
DSpaceServicesFactory.getInstance()
|
||||||
|
.getServiceManager()
|
||||||
|
.registerServiceClass(
|
||||||
|
VersionedHandleIdentifierProviderWithCanonicalHandles.class.getCanonicalName(),
|
||||||
|
VersionedHandleIdentifierProviderWithCanonicalHandles.class);
|
||||||
|
|
||||||
|
curator.curate(context, item);
|
||||||
|
System.out.format("With incompatible provider, result is '%s'.\n",
|
||||||
|
curator.getResult(TASK_NAME));
|
||||||
|
assertEquals("Curation should fail", Curator.CURATE_ERROR,
|
||||||
|
curator.getStatus(TASK_NAME));
|
||||||
|
}
|
||||||
|
}
|
@@ -15,7 +15,9 @@ import java.net.MalformedURLException;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@@ -229,14 +231,20 @@ public class RequestItemRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for authorized user
|
// Check for authorized user
|
||||||
RequestItemAuthor authorizer;
|
List<RequestItemAuthor> authorizers;
|
||||||
try {
|
try {
|
||||||
authorizer = requestItemAuthorExtractor.getRequestItemAuthor(context, ri.getItem());
|
authorizers = requestItemAuthorExtractor.getRequestItemAuthor(context, ri.getItem());
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
LOG.warn("Failed to find an authorizer: {}", ex.getMessage());
|
LOG.warn("Failed to find an authorizer: {}", ex.getMessage());
|
||||||
authorizer = new RequestItemAuthor("", "");
|
authorizers = Collections.EMPTY_LIST;
|
||||||
}
|
}
|
||||||
if (!authorizer.getEmail().equals(context.getCurrentUser().getEmail())) {
|
|
||||||
|
boolean authorized = false;
|
||||||
|
String requester = context.getCurrentUser().getEmail();
|
||||||
|
for (RequestItemAuthor authorizer : authorizers) {
|
||||||
|
authorized |= authorizer.getEmail().equals(requester);
|
||||||
|
}
|
||||||
|
if (!authorized) {
|
||||||
throw new AuthorizeException("Not authorized to approve this request");
|
throw new AuthorizeException("Not authorized to approve this request");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -251,7 +251,10 @@ public class UsageReportUtils {
|
|||||||
for (int i = 0; i < dataset.getColLabels().size(); i++) {
|
for (int i = 0; i < dataset.getColLabels().size(); i++) {
|
||||||
UsageReportPointDsoTotalVisitsRest totalDownloadsPoint = new UsageReportPointDsoTotalVisitsRest();
|
UsageReportPointDsoTotalVisitsRest totalDownloadsPoint = new UsageReportPointDsoTotalVisitsRest();
|
||||||
totalDownloadsPoint.setType("bitstream");
|
totalDownloadsPoint.setType("bitstream");
|
||||||
totalDownloadsPoint.setId(dataset.getColLabels().get(i));
|
|
||||||
|
totalDownloadsPoint.setId(dataset.getColLabelsAttrs().get(i).get("id"));
|
||||||
|
totalDownloadsPoint.setLabel(dataset.getColLabels().get(i));
|
||||||
|
|
||||||
totalDownloadsPoint.addValue("views", Integer.valueOf(dataset.getMatrix()[0][i]));
|
totalDownloadsPoint.addValue("views", Integer.valueOf(dataset.getMatrix()[0][i]));
|
||||||
usageReportRest.addPoint(totalDownloadsPoint);
|
usageReportRest.addPoint(totalDownloadsPoint);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -995,6 +995,305 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
|
|||||||
bibtex.close();
|
bibtex.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the creation of workspaceitems POSTing to the resource collection endpoint a bibtex file
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void createSingleWorkspaceItemFromBibtexArticleFileWithOneEntryTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
//** GIVEN **
|
||||||
|
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||||
|
.withName("Sub Community")
|
||||||
|
.build();
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, child1)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.withSubmitterGroup(eperson)
|
||||||
|
.build();
|
||||||
|
Collection col2 = CollectionBuilder.createCollection(context, child1)
|
||||||
|
.withName("Collection 2")
|
||||||
|
.withSubmitterGroup(eperson)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InputStream bibtex = getClass().getResourceAsStream("bibtex-test-article.bib");
|
||||||
|
final MockMultipartFile bibtexFile = new MockMultipartFile("file", "/local/path/bibtex-test-article.bib",
|
||||||
|
"application/x-bibtex", bibtex);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
AtomicReference<List<Integer>> idRef = new AtomicReference<>();
|
||||||
|
String authToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
try {
|
||||||
|
// create a workspaceitem from a single bibliographic entry file explicitly in the default collection (col1)
|
||||||
|
getClient(authToken).perform(multipart("/api/submission/workspaceitems")
|
||||||
|
.file(bibtexFile))
|
||||||
|
// create should return 200, 201 (created) is better for single resource
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.title'][0].value",
|
||||||
|
is("My Article")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.type'][0].value",
|
||||||
|
is("article")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[0]._embedded.collection.id",
|
||||||
|
is(col1.getID().toString())))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.source'][0].value",
|
||||||
|
is("/local/path/bibtex-test-article.bib")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.title'][0].value",
|
||||||
|
is("bibtex-test-article.bib")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist())
|
||||||
|
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
|
||||||
|
"$._embedded.workspaceitems[*].id")));
|
||||||
|
} finally {
|
||||||
|
if (idRef != null && idRef.get() != null) {
|
||||||
|
for (int i : idRef.get()) {
|
||||||
|
WorkspaceItemBuilder.deleteWorkspaceItem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a workspaceitem from a single bibliographic entry file explicitly in the col2
|
||||||
|
try {
|
||||||
|
getClient(authToken).perform(multipart("/api/submission/workspaceitems")
|
||||||
|
.file(bibtexFile)
|
||||||
|
.param("owningCollection", col2.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.title'][0].value",
|
||||||
|
is("My Article")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.type'][0].value",
|
||||||
|
is("article")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[0]._embedded.collection.id",
|
||||||
|
is(col2.getID().toString())))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.source'][0].value",
|
||||||
|
is("/local/path/bibtex-test-article.bib")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload"
|
||||||
|
+ ".files[0].metadata['dc.title'][0].value",
|
||||||
|
is("bibtex-test-article.bib")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist())
|
||||||
|
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
|
||||||
|
"$._embedded.workspaceitems[*].id")));
|
||||||
|
} finally {
|
||||||
|
if (idRef != null && idRef.get() != null) {
|
||||||
|
for (int i : idRef.get()) {
|
||||||
|
WorkspaceItemBuilder.deleteWorkspaceItem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bibtex.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createSingleWorkspaceItemFromBibtexFileWithDiacriticsTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
//** GIVEN **
|
||||||
|
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||||
|
.withName("Sub Community")
|
||||||
|
.build();
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, child1)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.withSubmitterGroup(eperson)
|
||||||
|
.build();
|
||||||
|
Collection col2 = CollectionBuilder.createCollection(context, child1)
|
||||||
|
.withName("Collection 2")
|
||||||
|
.withSubmitterGroup(eperson)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InputStream bibtex = getClass().getResourceAsStream("bibtex-test-diacritics.bib");
|
||||||
|
final MockMultipartFile bibtexFile = new MockMultipartFile("file", "/local/path/bibtex-test-diacritics.bib",
|
||||||
|
"application/x-bibtex", bibtex);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
AtomicReference<List<Integer>> idRef = new AtomicReference<>();
|
||||||
|
String authToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
try {
|
||||||
|
// create a workspaceitem from a single bibliographic entry file explicitly in the default collection (col1)
|
||||||
|
getClient(authToken).perform(multipart("/api/submission/workspaceitems")
|
||||||
|
.file(bibtexFile))
|
||||||
|
// create should return 200, 201 (created) is better for single resource
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections." +
|
||||||
|
"traditionalpageone['dc.title'][0].value",
|
||||||
|
is("The German umlauts: ÄÖüß")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[0]._embedded.collection.id",
|
||||||
|
is(col1.getID().toString())))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.source'][0].value",
|
||||||
|
is("/local/path/bibtex-test-diacritics.bib")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.title'][0].value",
|
||||||
|
is("bibtex-test-diacritics.bib")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist())
|
||||||
|
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
|
||||||
|
"$._embedded.workspaceitems[*].id")));
|
||||||
|
} finally {
|
||||||
|
if (idRef != null && idRef.get() != null) {
|
||||||
|
for (int i : idRef.get()) {
|
||||||
|
WorkspaceItemBuilder.deleteWorkspaceItem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a workspaceitem from a single bibliographic entry file explicitly in the col2
|
||||||
|
try {
|
||||||
|
getClient(authToken).perform(multipart("/api/submission/workspaceitems")
|
||||||
|
.file(bibtexFile)
|
||||||
|
.param("owningCollection", col2.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections." +
|
||||||
|
"traditionalpageone['dc.title'][0].value",
|
||||||
|
is("The German umlauts: ÄÖüß")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[0]._embedded.collection.id",
|
||||||
|
is(col2.getID().toString())))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.source'][0].value",
|
||||||
|
is("/local/path/bibtex-test-diacritics.bib")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload"
|
||||||
|
+ ".files[0].metadata['dc.title'][0].value",
|
||||||
|
is("bibtex-test-diacritics.bib")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist())
|
||||||
|
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
|
||||||
|
"$._embedded.workspaceitems[*].id")));
|
||||||
|
} finally {
|
||||||
|
if (idRef != null && idRef.get() != null) {
|
||||||
|
for (int i : idRef.get()) {
|
||||||
|
WorkspaceItemBuilder.deleteWorkspaceItem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bibtex.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
/**
|
||||||
|
* Test the creation of workspaceitems POSTing to the resource collection endpoint a bibtex file
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void createSingleWorkspaceItemFromBibtexFileWithMultipleAuthorsTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
//** GIVEN **
|
||||||
|
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||||
|
.withName("Sub Community")
|
||||||
|
.build();
|
||||||
|
Collection col1 = CollectionBuilder.createCollection(context, child1)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.withSubmitterGroup(eperson)
|
||||||
|
.build();
|
||||||
|
Collection col2 = CollectionBuilder.createCollection(context, child1)
|
||||||
|
.withName("Collection 2")
|
||||||
|
.withSubmitterGroup(eperson)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InputStream bibtex = getClass().getResourceAsStream("bibtex-test-multiple-authors.bib");
|
||||||
|
final MockMultipartFile bibtexFile = new MockMultipartFile("file",
|
||||||
|
"/local/path/bibtex-test-multiple-authors.bib",
|
||||||
|
"application/x-bibtex", bibtex);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
AtomicReference<List<Integer>> idRef = new AtomicReference<>();
|
||||||
|
String authToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
try {
|
||||||
|
// create a workspaceitem from a single bibliographic entry file explicitly in the default collection (col1)
|
||||||
|
getClient(authToken).perform(multipart("/api/submission/workspaceitems")
|
||||||
|
.file(bibtexFile))
|
||||||
|
// create should return 200, 201 (created) is better for single resource
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.title'][0].value",
|
||||||
|
is("My Article")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.contributor.author'][0].value",
|
||||||
|
is("A. Nauthor")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.contributor.author'][1].value",
|
||||||
|
is("A. Nother")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.contributor.author'][2].value",
|
||||||
|
is("A. Third")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[0]._embedded.collection.id",
|
||||||
|
is(col1.getID().toString())))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.source'][0].value",
|
||||||
|
is("/local/path/bibtex-test-multiple-authors.bib")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.title'][0].value",
|
||||||
|
is("bibtex-test-multiple-authors.bib")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist())
|
||||||
|
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
|
||||||
|
"$._embedded.workspaceitems[*].id")));
|
||||||
|
} finally {
|
||||||
|
if (idRef != null && idRef.get() != null) {
|
||||||
|
for (int i : idRef.get()) {
|
||||||
|
WorkspaceItemBuilder.deleteWorkspaceItem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a workspaceitem from a single bibliographic entry file explicitly in the col2
|
||||||
|
try {
|
||||||
|
getClient(authToken).perform(multipart("/api/submission/workspaceitems")
|
||||||
|
.file(bibtexFile)
|
||||||
|
.param("owningCollection", col2.getID().toString()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0]" +
|
||||||
|
".sections.traditionalpageone['dc.title'][0].value",
|
||||||
|
is("My Article")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[0]._embedded.collection.id",
|
||||||
|
is(col2.getID().toString())))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0]"
|
||||||
|
+ ".metadata['dc.source'][0].value",
|
||||||
|
is("/local/path/bibtex-test-multiple-authors.bib")))
|
||||||
|
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.upload"
|
||||||
|
+ ".files[0].metadata['dc.title'][0].value",
|
||||||
|
is("bibtex-test-multiple-authors.bib")))
|
||||||
|
.andExpect(
|
||||||
|
jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist())
|
||||||
|
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(),
|
||||||
|
"$._embedded.workspaceitems[*].id")));
|
||||||
|
} finally {
|
||||||
|
if (idRef != null && idRef.get() != null) {
|
||||||
|
for (int i : idRef.get()) {
|
||||||
|
WorkspaceItemBuilder.deleteWorkspaceItem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bibtex.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
/**
|
/**
|
||||||
* Test the creation of workspaceitems POSTing to the resource collection endpoint a csv file
|
* Test the creation of workspaceitems POSTing to the resource collection endpoint a csv file
|
||||||
|
@@ -142,10 +142,10 @@ public class DeleteEPersonSubmitterIT extends AbstractControllerIntegrationTest
|
|||||||
|
|
||||||
|
|
||||||
Item item = itemService.find(context, installItem.getID());
|
Item item = itemService.find(context, installItem.getID());
|
||||||
RequestItemAuthor requestItemAuthor = requestItemAuthorExtractor.getRequestItemAuthor(context, item);
|
List<RequestItemAuthor> requestItemAuthor = requestItemAuthorExtractor.getRequestItemAuthor(context, item);
|
||||||
|
|
||||||
assertEquals("Help Desk", requestItemAuthor.getFullName());
|
assertEquals("Help Desk", requestItemAuthor.get(0).getFullName());
|
||||||
assertEquals("dspace-help@myu.edu", requestItemAuthor.getEmail());
|
assertEquals("dspace-help@myu.edu", requestItemAuthor.get(0).getEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,7 +171,7 @@ public class DeleteEPersonSubmitterIT extends AbstractControllerIntegrationTest
|
|||||||
|
|
||||||
Item item = installItemService.installItem(context, wsi);
|
Item item = installItemService.installItem(context, wsi);
|
||||||
|
|
||||||
List<Operation> opsToWithDraw = new ArrayList<Operation>();
|
List<Operation> opsToWithDraw = new ArrayList<>();
|
||||||
ReplaceOperation replaceOperationToWithDraw = new ReplaceOperation("/withdrawn", true);
|
ReplaceOperation replaceOperationToWithDraw = new ReplaceOperation("/withdrawn", true);
|
||||||
opsToWithDraw.add(replaceOperationToWithDraw);
|
opsToWithDraw.add(replaceOperationToWithDraw);
|
||||||
String patchBodyToWithdraw = getPatchContent(opsToWithDraw);
|
String patchBodyToWithdraw = getPatchContent(opsToWithDraw);
|
||||||
@@ -191,7 +191,7 @@ public class DeleteEPersonSubmitterIT extends AbstractControllerIntegrationTest
|
|||||||
|
|
||||||
assertNull(retrieveItemSubmitter(item.getID()));
|
assertNull(retrieveItemSubmitter(item.getID()));
|
||||||
|
|
||||||
List<Operation> opsToReinstate = new ArrayList<Operation>();
|
List<Operation> opsToReinstate = new ArrayList<>();
|
||||||
ReplaceOperation replaceOperationToReinstate = new ReplaceOperation("/withdrawn", false);
|
ReplaceOperation replaceOperationToReinstate = new ReplaceOperation("/withdrawn", false);
|
||||||
opsToReinstate.add(replaceOperationToReinstate);
|
opsToReinstate.add(replaceOperationToReinstate);
|
||||||
String patchBodyToReinstate = getPatchContent(opsToReinstate);
|
String patchBodyToReinstate = getPatchContent(opsToReinstate);
|
||||||
|
@@ -49,13 +49,18 @@ public class UsageReportMatcher {
|
|||||||
* @param points List of points to match to the json of UsageReport's list of points
|
* @param points List of points to match to the json of UsageReport's list of points
|
||||||
* @return The matcher
|
* @return The matcher
|
||||||
*/
|
*/
|
||||||
public static Matcher<? super Object> matchUsageReport(String id, String reportType,
|
public static Matcher<? super Object> matchUsageReport(
|
||||||
List<UsageReportPointRest> points) {
|
String id, String reportType, List<UsageReportPointRest> points
|
||||||
|
) {
|
||||||
return allOf(
|
return allOf(
|
||||||
matchUsageReport(id, reportType),
|
matchUsageReport(id, reportType),
|
||||||
hasJsonPath("$.points", Matchers.containsInAnyOrder(
|
hasJsonPath("$.points", Matchers.containsInAnyOrder(
|
||||||
points.stream().map(point -> UsageReportPointMatcher
|
points.stream()
|
||||||
.matchUsageReportPoint(point.getId(), point.getType(), point.getValues().get("views")))
|
.map(point -> UsageReportPointMatcher.matchUsageReportPoint(
|
||||||
.collect(Collectors.toList()))));
|
point.getId(), point.getLabel(), point.getType(), point.getValues().get("views")
|
||||||
|
))
|
||||||
|
.collect(Collectors.toList()))
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,13 +28,15 @@ public class UsageReportPointMatcher {
|
|||||||
* Matcher for the usage report points (see {@link UsageReportPointRest})
|
* Matcher for the usage report points (see {@link UsageReportPointRest})
|
||||||
*
|
*
|
||||||
* @param id Id to match if of json of UsageReportPoint
|
* @param id Id to match if of json of UsageReportPoint
|
||||||
|
* @param label Label to match if of json of UsageReportPoint
|
||||||
* @param type Type to match if of json of UsageReportPoint
|
* @param type Type to match if of json of UsageReportPoint
|
||||||
* @param views Nr of views, is in the values key-value pair of values of UsageReportPoint with key "views"
|
* @param views Nr of views, is in the values key-value pair of values of UsageReportPoint with key "views"
|
||||||
* @return The matcher
|
* @return The matcher
|
||||||
*/
|
*/
|
||||||
public static Matcher<? super Object> matchUsageReportPoint(String id, String type, int views) {
|
public static Matcher<? super Object> matchUsageReportPoint(String id, String label, String type, int views) {
|
||||||
return allOf(
|
return allOf(
|
||||||
hasJsonPath("$.id", is(id)),
|
hasJsonPath("$.id", is(id)),
|
||||||
|
hasJsonPath("$.label", is(label)),
|
||||||
hasJsonPath("$.type", is(type)),
|
hasJsonPath("$.type", is(type)),
|
||||||
hasJsonPath("$.values.views", is(views))
|
hasJsonPath("$.values.views", is(views))
|
||||||
);
|
);
|
||||||
|
@@ -0,0 +1,4 @@
|
|||||||
|
@article{ Nobody01,
|
||||||
|
author = "Nobody Jr",
|
||||||
|
title = "My Article",
|
||||||
|
year = "2006" }
|
@@ -0,0 +1,4 @@
|
|||||||
|
@misc{ Nobody01,
|
||||||
|
author = "Mo\ss",
|
||||||
|
title = { The German umlauts: \"A{\"O}{\"{u}}\ss },
|
||||||
|
year = "2006" }
|
@@ -0,0 +1,4 @@
|
|||||||
|
@misc{ Nobody01,
|
||||||
|
author = "A. Nauthor and A. Nother and A. Third",
|
||||||
|
title = "My Article",
|
||||||
|
year = "2006" }
|
@@ -5,8 +5,7 @@
|
|||||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||||
|
|
||||||
<bean id="uploadConfigurationDefault" class="org.dspace.submit.model.UploadConfiguration">
|
<bean id="uploadConfigurationDefault" class="org.dspace.submit.model.UploadConfiguration">
|
||||||
<property name="name" value="upload"></property>
|
<property name="name" value="upload"/>
|
||||||
<property name="configurationService" ref="org.dspace.services.ConfigurationService"/>
|
|
||||||
<property name="metadata" value="bitstream-metadata" />
|
<property name="metadata" value="bitstream-metadata" />
|
||||||
<property name="options">
|
<property name="options">
|
||||||
<list>
|
<list>
|
||||||
@@ -38,7 +37,6 @@
|
|||||||
<property name="hasStartDate" value="true"/>
|
<property name="hasStartDate" value="true"/>
|
||||||
<property name="startDateLimit" value="+36MONTHS"/>
|
<property name="startDateLimit" value="+36MONTHS"/>
|
||||||
<property name="hasEndDate" value="false"/>
|
<property name="hasEndDate" value="false"/>
|
||||||
|
|
||||||
</bean>
|
</bean>
|
||||||
<bean id="administrator" class="org.dspace.submit.model.AccessConditionOption">
|
<bean id="administrator" class="org.dspace.submit.model.AccessConditionOption">
|
||||||
<property name="groupName" value="Administrator"/>
|
<property name="groupName" value="Administrator"/>
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
only matters here for postprocessing of the value. The mapped MetadatumContributor has full control over
|
only matters here for postprocessing of the value. The mapped MetadatumContributor has full control over
|
||||||
what metadatafield is generated.
|
what metadatafield is generated.
|
||||||
</description>
|
</description>
|
||||||
|
<entry key-ref="dcType" value-ref="bibtexTypeContrib" />
|
||||||
<entry key-ref="dcTitle" value-ref="bibtexTitleContrib" />
|
<entry key-ref="dcTitle" value-ref="bibtexTitleContrib" />
|
||||||
<entry key-ref="dcAuthors" value-ref="bibtexAuthorsContrib" />
|
<entry key-ref="dcAuthors" value-ref="bibtexAuthorsContrib" />
|
||||||
<entry key-ref="dcJournal" value-ref="bibtexJournalContrib" />
|
<entry key-ref="dcJournal" value-ref="bibtexJournalContrib" />
|
||||||
@@ -39,14 +40,24 @@
|
|||||||
<property name="key" value="journal" />
|
<property name="key" value="journal" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="bibtexAuthorsContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleMetadataContributor">
|
<bean id="bibtexAuthorsContrib" class="org.dspace.importer.external.metadatamapping.contributor.SplitMetadataContributor">
|
||||||
|
<constructor-arg name="innerContributor">
|
||||||
|
<bean class="org.dspace.importer.external.metadatamapping.contributor.SimpleMetadataContributor">
|
||||||
<property name="field" ref="dcAuthors"/>
|
<property name="field" ref="dcAuthors"/>
|
||||||
<property name="key" value="author" />
|
<property name="key" value="author" />
|
||||||
</bean>
|
</bean>
|
||||||
|
</constructor-arg>
|
||||||
|
<constructor-arg name="regex" value="\sand\s"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="bibtexTitleContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleMetadataContributor">
|
<bean id="bibtexTitleContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleMetadataContributor">
|
||||||
<property name="field" ref="dcTitle"/>
|
<property name="field" ref="dcTitle"/>
|
||||||
<property name="key" value="title" />
|
<property name="key" value="title" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="bibtexTypeContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleMetadataContributor">
|
||||||
|
<property name="field" ref="dcType"/>
|
||||||
|
<property name="key" value="type" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
@@ -25,6 +25,9 @@
|
|||||||
</bean>
|
</bean>
|
||||||
<bean id="dcTitle" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
<bean id="dcTitle" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
<constructor-arg value="dc.title"/>
|
<constructor-arg value="dc.title"/>
|
||||||
|
</bean>
|
||||||
|
<bean id="dcType" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.type"/>
|
||||||
</bean>
|
</bean>
|
||||||
<bean id="dcAuthors" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
<bean id="dcAuthors" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
<constructor-arg value="dc.contributor.author"/>
|
<constructor-arg value="dc.contributor.author"/>
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:util="http://www.springframework.org/schema/util"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/util
|
||||||
|
http://www.springframework.org/schema/util/spring-util.xsd"
|
||||||
default-lazy-init="true">
|
default-lazy-init="true">
|
||||||
|
|
||||||
<bean id="openAIRERestConnector" class="org.dspace.external.OpenAIRERestConnector">
|
<bean id="openAIRERestConnector" class="org.dspace.external.OpenAIRERestConnector">
|
||||||
@@ -10,11 +14,11 @@
|
|||||||
<property name="clientId" value="${openaire.token.clientId}"/>
|
<property name="clientId" value="${openaire.token.clientId}"/>
|
||||||
<property name="clientSecret" value="${openaire.token.clientSecret}"/>
|
<property name="clientSecret" value="${openaire.token.clientSecret}"/>
|
||||||
</bean>
|
</bean>
|
||||||
<bean
|
|
||||||
class="org.dspace.external.provider.impl.OpenAIREFundingDataProvider"
|
<bean class="org.dspace.external.provider.impl.OpenAIREFundingDataProvider" init-method="init">
|
||||||
init-method="init">
|
|
||||||
<property name="sourceIdentifier" value="openAIREFunding" />
|
<property name="sourceIdentifier" value="openAIREFunding" />
|
||||||
<property name="connector" ref="openAIRERestConnector" />
|
<property name="connector" ref="openAIRERestConnector" />
|
||||||
|
<property name="metadataFields" ref="mapOfmetadata"/>
|
||||||
<property name="supportedEntityTypes">
|
<property name="supportedEntityTypes">
|
||||||
<list>
|
<list>
|
||||||
<value>Project</value>
|
<value>Project</value>
|
||||||
@@ -22,5 +26,53 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
</beans>
|
<util:map id="mapOfmetadata"
|
||||||
|
map-class="java.util.HashMap" key-type="java.lang.String" value-type="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<entry key="awardNumber" value-ref="openaireAwardNumber" />
|
||||||
|
<entry key="fundingStream" value-ref="openaireFundingStream" />
|
||||||
|
<entry key="awardURI" value-ref="openaireAwardURI" />
|
||||||
|
<entry key="funderName" value-ref="openaireFunderName" />
|
||||||
|
<entry key="funderIdentifier" value-ref="openaireFunderIdentifier" />
|
||||||
|
<entry key="dcTitle" value-ref="openaireTitle" />
|
||||||
|
<entry key="titleAlternative" value-ref="openaireTitleAlternative" />
|
||||||
|
<entry key="coverageSpatial" value-ref="openaireSpatial" />
|
||||||
|
<entry key="dcSubject" value-ref="openaireSubject" />
|
||||||
|
</util:map>
|
||||||
|
|
||||||
|
<bean id="openaireAwardNumber" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="oaire.awardNumber"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireFundingStream" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="oaire.fundingStream"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireAwardURI" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="oaire.awardURI"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireFunderName" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="project.funder.name"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireFunderIdentifier" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="project.funder.identifier"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireTitle" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.title"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireTitleAlternative" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.title.alternative"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireSpatial" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.coverage.spatial"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="openaireSubject" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
|
<constructor-arg value="dc.subject"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
@@ -8,25 +8,65 @@
|
|||||||
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
|
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
|
||||||
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
Strategies for determining who receives Request Copy emails.
|
||||||
|
A copy request "strategy" class produces a list of addresses to which a
|
||||||
|
request email should be sent. Each strategy gets its addresses from a
|
||||||
|
different source. Select the one that meets your need, or use the
|
||||||
|
CombiningRequestItemStrategy to meld the lists from two or more other
|
||||||
|
strategies.
|
||||||
|
</description>
|
||||||
|
|
||||||
<context:annotation-config /> <!-- allows us to use Spring annotations in beans -->
|
<context:annotation-config /> <!-- allows us to use Spring annotations in beans -->
|
||||||
|
|
||||||
<bean class="org.dspace.app.requestitem.RequestItemMetadataStrategy"
|
<!-- Select the implementation to be used. -->
|
||||||
id="org.dspace.app.requestitem.RequestItemAuthorExtractor"
|
<alias alias='org.dspace.app.requestitem.RequestItemAuthorExtractor'
|
||||||
autowire-candidate='true'>
|
name='org.dspace.app.requestitem.RequestItemMetadataStrategy'/>
|
||||||
<!--
|
|
||||||
Uncomment these properties if you want lookup in metadata the email and
|
|
||||||
the name of the author to contact for request copy.
|
|
||||||
If you don't configure that or if the requested item doesn't have these
|
|
||||||
metadata, the submitter data are used as fail over.
|
|
||||||
|
|
||||||
<property name="emailMetadata" value="schema.element.qualifier" />
|
<!-- Get recipients from an item metadata field. -->
|
||||||
<property name="fullNameMetadata" value="schema.element.qualifier" />
|
<bean class="org.dspace.app.requestitem.RequestItemMetadataStrategy"
|
||||||
|
id="org.dspace.app.requestitem.RequestItemMetadataStrategy"
|
||||||
|
autowire-candidate="true">
|
||||||
|
<!--
|
||||||
|
Uncomment these properties if you want lookup in metadata the email
|
||||||
|
and the name of the author to contact for request copy.
|
||||||
|
If you don't configure that or if the requested item doesn't have
|
||||||
|
these metadata, the submitter data are used as fail over.
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
|
||||||
|
<property name="emailMetadata"
|
||||||
|
value="schema.element.qualifier" />
|
||||||
|
<property name="fullNameMetadata"
|
||||||
|
value="schema.element.qualifier" />
|
||||||
-->
|
-->
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- HelpDesk to instead get RequestItem emails-->
|
<!-- HelpDesk to instead get RequestItem emails-->
|
||||||
<!--<bean class="org.dspace.app.requestitem.RequestItemHelpdeskStrategy"
|
<!--
|
||||||
id="org.dspace.app.requestitem.RequestItemAuthorExtractor"
|
<bean class="org.dspace.app.requestitem.RequestItemHelpdeskStrategy"
|
||||||
autowire-candidate='true'></bean>-->
|
id="org.dspace.app.requestitem.RequestItemHelpdeskStrategy"/>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Send request emails to administrators of an Item's owning Collection. -->
|
||||||
|
<!--
|
||||||
|
<bean class='org.dspace.app.requestitem.CollectionAdministratorsRequestItemStrategy'
|
||||||
|
id='org.dspace.app.requestitem.CollectionAdministratorsRequestItemStrategy'/>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Execute multiple strategies and concatenate their lists of recipients.
|
||||||
|
Mail will go to all members of the combined list. -->
|
||||||
|
<!--
|
||||||
|
<bean class='org.dspace.app.requestitem.CombiningRequestItemStrategy'
|
||||||
|
id='org.dspace.app.requestitem.CombiningRequestItemStrategy'
|
||||||
|
autowire='no'>
|
||||||
|
<constructor-arg>
|
||||||
|
<description>A list of references to RequestItemAuthorExtractor beans</description>
|
||||||
|
<list>
|
||||||
|
<ref bean='org.dspace.app.requestitem.RequestItemMetadataStrategy'/>
|
||||||
|
<ref bean='org.dspace.app.requestitem.CollectionAdministratorsRequestItemStrategy'/>
|
||||||
|
</list>
|
||||||
|
</constructor-arg>
|
||||||
|
</bean>
|
||||||
|
-->
|
||||||
</beans>
|
</beans>
|
||||||
|
11
pom.xml
11
pom.xml
@@ -1575,18 +1575,11 @@
|
|||||||
<artifactId>ojdbc6</artifactId>
|
<artifactId>ojdbc6</artifactId>
|
||||||
<version>11.2.0.4.0</version>
|
<version>11.2.0.4.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Codebase at https://github.com/OCLC-Research/oaiharvester2/ -->
|
<!-- Codebase at https://github.com/DSpace/oclc-harvester2 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dspace</groupId>
|
<groupId>org.dspace</groupId>
|
||||||
<artifactId>oclc-harvester2</artifactId>
|
<artifactId>oclc-harvester2</artifactId>
|
||||||
<version>0.1.12</version>
|
<version>1.0.0</version>
|
||||||
</dependency>
|
|
||||||
<!-- Xalan is REQUIRED by 'oclc-harvester2' listed above (OAI harvesting fails without it).
|
|
||||||
Please do NOT use Xalan in DSpace codebase as it is not well maintained. -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>xalan</groupId>
|
|
||||||
<artifactId>xalan</artifactId>
|
|
||||||
<version>2.7.2</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
Reference in New Issue
Block a user