bundles = item.getBundles("ORIGINAL");
@@ -179,11 +180,19 @@ static public void sendResponse(Context context, RequestItem ri, String subject,
bitstream.getFormat(context).getMIMEType());
}
email.send();
- } catch (MessagingException | IOException | SQLException | AuthorizeException e) {
- LOG.warn(LogHelper.getHeader(context,
- "error_mailing_requestItem", e.getMessage()));
- throw new IOException("Reply not sent: " + e.getMessage());
+ } else {
+ boolean sendRejectEmail = configurationService
+ .getBooleanProperty("request.item.reject.email", true);
+ // Not all sites want the "refusal" to be sent back to the requester via
+ // email. However, by default, the rejection email is sent back.
+ if (sendRejectEmail) {
+ email.send();
+ }
}
+ } catch (MessagingException | IOException | SQLException | AuthorizeException e) {
+ LOG.warn(LogHelper.getHeader(context,
+ "error_mailing_requestItem", e.getMessage()));
+ throw new IOException("Reply not sent: " + e.getMessage());
}
LOG.info(LogHelper.getHeader(context,
"sent_attach_requestItem", "token={}"), ri.getToken());
@@ -220,8 +229,13 @@ static public void requestOpenAccess(Context context, RequestItem ri)
message.addArgument(bitstreamName); // {0} bitstream name or "all"
message.addArgument(item.getHandle()); // {1} Item handle
message.addArgument(ri.getToken()); // {2} Request token
- message.addArgument(approver.getFullName()); // {3} Approver's name
- message.addArgument(approver.getEmail()); // {4} Approver's address
+ if (approver != null) {
+ message.addArgument(approver.getFullName()); // {3} Approver's name
+ message.addArgument(approver.getEmail()); // {4} Approver's address
+ } else {
+ message.addArgument("anonymous approver"); // [3] Approver's name
+ message.addArgument(configurationService.getProperty("mail.admin")); // [4] Approver's address
+ }
// Who gets this message?
String recipient;
diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemHelpdeskStrategy.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemHelpdeskStrategy.java
index f440ba380a0e..dee0ed7a2351 100644
--- a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemHelpdeskStrategy.java
+++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemHelpdeskStrategy.java
@@ -22,21 +22,27 @@
import org.springframework.lang.NonNull;
/**
- * 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.
+ * RequestItem strategy to allow DSpace support team's help desk to receive
+ * requestItem requests. With this enabled, the Item author/submitter doesn't
+ * receive the request, but the help desk instead does.
*
- * Failover to the RequestItemSubmitterStrategy, which means the submitter would get the request if there is no
- * specified helpdesk email.
+ * Fails over to the {@link RequestItemSubmitterStrategy}, which means the
+ * submitter would get the request if there is no specified help desk email.
*
* @author Sam Ottenhoff
* @author Peter Dietz
*/
-public class RequestItemHelpdeskStrategy extends RequestItemSubmitterStrategy {
+public class RequestItemHelpdeskStrategy
+ extends RequestItemSubmitterStrategy {
+ static final String P_HELPDESK_OVERRIDE
+ = "request.item.helpdesk.override";
+ static final String P_MAIL_HELPDESK = "mail.helpdesk";
+
@Autowired(required = true)
protected EPersonService ePersonService;
@Autowired(required = true)
- private ConfigurationService configuration;
+ protected ConfigurationService configurationService;
public RequestItemHelpdeskStrategy() {
}
@@ -45,9 +51,9 @@ public RequestItemHelpdeskStrategy() {
@NonNull
public List getRequestItemAuthor(Context context, Item item)
throws SQLException {
- boolean helpdeskOverridesSubmitter = configuration
+ boolean helpdeskOverridesSubmitter = configurationService
.getBooleanProperty("request.item.helpdesk.override", false);
- String helpDeskEmail = configuration.getProperty("mail.helpdesk");
+ String helpDeskEmail = configurationService.getProperty("mail.helpdesk");
if (helpdeskOverridesSubmitter && StringUtils.isNotBlank(helpDeskEmail)) {
List authors = new ArrayList<>(1);
@@ -60,16 +66,18 @@ public List getRequestItemAuthor(Context context, Item item)
}
/**
- * Return a RequestItemAuthor object for the specified helpdesk email address.
- * It makes an attempt to find if there is a matching eperson for the helpdesk address, to use the name,
- * Otherwise it falls back to a helpdeskname key in the Messages.props.
+ * Return a RequestItemAuthor object for the specified help desk email address.
+ * It makes an attempt to find if there is a matching {@link EPerson} for
+ * the help desk address, to use its name. Otherwise it falls back to the
+ * {@code helpdeskname} key in {@code Messages.properties}.
*
* @param context context
* @param helpDeskEmail email
* @return RequestItemAuthor
* @throws SQLException if database error
*/
- public RequestItemAuthor getHelpDeskPerson(Context context, String helpDeskEmail) throws SQLException {
+ public RequestItemAuthor getHelpDeskPerson(Context context, String helpDeskEmail)
+ throws SQLException {
context.turnOffAuthorisationSystem();
EPerson helpdeskEPerson = ePersonService.findByEmail(context, helpDeskEmail);
context.restoreAuthSystemState();
diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemServiceImpl.java
index d2b249f6ec9f..b915cfedd346 100644
--- a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemServiceImpl.java
@@ -9,6 +9,7 @@
import java.sql.SQLException;
import java.util.Date;
+import java.util.Iterator;
import java.util.List;
import org.apache.logging.log4j.LogManager;
@@ -90,6 +91,11 @@ public RequestItem findByToken(Context context, String token) {
}
}
+ @Override
+ public Iterator findByItem(Context context, Item item) throws SQLException {
+ return requestItemDAO.findByItem(context, item);
+ }
+
@Override
public void update(Context context, RequestItem requestItem) {
try {
diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemSubmitterStrategy.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemSubmitterStrategy.java
index dcc1a3e80eac..6cfeee442600 100644
--- a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemSubmitterStrategy.java
+++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemSubmitterStrategy.java
@@ -22,7 +22,6 @@
* @author Andrea Bollini
*/
public class RequestItemSubmitterStrategy implements RequestItemAuthorExtractor {
-
public RequestItemSubmitterStrategy() {
}
diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/dao/RequestItemDAO.java b/dspace-api/src/main/java/org/dspace/app/requestitem/dao/RequestItemDAO.java
index 4a4ea6cd905d..b36ae58e0ca1 100644
--- a/dspace-api/src/main/java/org/dspace/app/requestitem/dao/RequestItemDAO.java
+++ b/dspace-api/src/main/java/org/dspace/app/requestitem/dao/RequestItemDAO.java
@@ -8,8 +8,10 @@
package org.dspace.app.requestitem.dao;
import java.sql.SQLException;
+import java.util.Iterator;
import org.dspace.app.requestitem.RequestItem;
+import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.core.GenericDAO;
@@ -32,4 +34,6 @@ public interface RequestItemDAO extends GenericDAO {
* @throws SQLException passed through.
*/
public RequestItem findByToken(Context context, String token) throws SQLException;
+
+ public Iterator findByItem(Context context, Item item) throws SQLException;
}
diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java
index fa1ed9ffeb64..008174ded88c 100644
--- a/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java
+++ b/dspace-api/src/main/java/org/dspace/app/requestitem/dao/impl/RequestItemDAOImpl.java
@@ -8,6 +8,8 @@
package org.dspace.app.requestitem.dao.impl;
import java.sql.SQLException;
+import java.util.Iterator;
+import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
@@ -15,6 +17,7 @@
import org.dspace.app.requestitem.RequestItem;
import org.dspace.app.requestitem.RequestItem_;
import org.dspace.app.requestitem.dao.RequestItemDAO;
+import org.dspace.content.Item;
import org.dspace.core.AbstractHibernateDAO;
import org.dspace.core.Context;
@@ -39,4 +42,10 @@ public RequestItem findByToken(Context context, String token) throws SQLExceptio
criteriaQuery.where(criteriaBuilder.equal(requestItemRoot.get(RequestItem_.token), token));
return uniqueResult(context, criteriaQuery, false, RequestItem.class);
}
+ @Override
+ public Iterator findByItem(Context context, Item item) throws SQLException {
+ Query query = createQuery(context, "FROM RequestItem WHERE item_id= :uuid");
+ query.setParameter("uuid", item.getID());
+ return iterate(query);
+ }
}
diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/service/RequestItemService.java b/dspace-api/src/main/java/org/dspace/app/requestitem/service/RequestItemService.java
index 5cab72e4e903..efac3b18bc7c 100644
--- a/dspace-api/src/main/java/org/dspace/app/requestitem/service/RequestItemService.java
+++ b/dspace-api/src/main/java/org/dspace/app/requestitem/service/RequestItemService.java
@@ -8,6 +8,7 @@
package org.dspace.app.requestitem.service;
import java.sql.SQLException;
+import java.util.Iterator;
import java.util.List;
import org.dspace.app.requestitem.RequestItem;
@@ -62,6 +63,14 @@ public List findAll(Context context)
*/
public RequestItem findByToken(Context context, String token);
+ /**
+ * Retrieve a request based on the item.
+ * @param context current DSpace session.
+ * @param item the item to find requests for.
+ * @return the matching requests, or null if not found.
+ */
+ public Iterator findByItem(Context context, Item item) throws SQLException;
+
/**
* Save updates to the record. Only accept_request, and decision_date are set-able.
*
diff --git a/dspace-api/src/main/java/org/dspace/app/suggestion/SuggestionSource.java b/dspace-api/src/main/java/org/dspace/app/suggestion/SuggestionSource.java
index b9df687dec32..ced841cbfa0e 100644
--- a/dspace-api/src/main/java/org/dspace/app/suggestion/SuggestionSource.java
+++ b/dspace-api/src/main/java/org/dspace/app/suggestion/SuggestionSource.java
@@ -24,7 +24,7 @@ public SuggestionSource() {
/**
* Summarize the available suggestions from a source.
*
- * @param the name must be not null
+ * @param name must be not null
*/
public SuggestionSource(String name) {
super();
diff --git a/dspace-api/src/main/java/org/dspace/app/suggestion/oaire/AuthorNamesScorer.java b/dspace-api/src/main/java/org/dspace/app/suggestion/oaire/AuthorNamesScorer.java
index f429ae017ce9..a209a3cefb9c 100644
--- a/dspace-api/src/main/java/org/dspace/app/suggestion/oaire/AuthorNamesScorer.java
+++ b/dspace-api/src/main/java/org/dspace/app/suggestion/oaire/AuthorNamesScorer.java
@@ -54,7 +54,6 @@ public List getContributorMetadata() {
/**
* set the metadata key of the Item which to base the filter on
- * @return metadata key
*/
public void setContributorMetadata(List contributorMetadata) {
this.contributorMetadata = contributorMetadata;
diff --git a/dspace-api/src/main/java/org/dspace/app/suggestion/oaire/EvidenceScorer.java b/dspace-api/src/main/java/org/dspace/app/suggestion/oaire/EvidenceScorer.java
index 9df7621b46bb..6e00fdef0d8a 100644
--- a/dspace-api/src/main/java/org/dspace/app/suggestion/oaire/EvidenceScorer.java
+++ b/dspace-api/src/main/java/org/dspace/app/suggestion/oaire/EvidenceScorer.java
@@ -32,6 +32,6 @@ public interface EvidenceScorer {
* @return the generated suggestion evidence or null if the record should be
* discarded
*/
- public SuggestionEvidence computeEvidence(Item researcher, ExternalDataObject importRecords);
+ public SuggestionEvidence computeEvidence(Item researcher, ExternalDataObject importRecord);
}
diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java
index f863fc65a28a..91c5c09440e9 100644
--- a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java
+++ b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java
@@ -221,7 +221,7 @@ public DCInput(Map fieldMap, Map> listMap)
|| "yes".equalsIgnoreCase(closedVocabularyStr);
// parsing of the element (using the colon as split separator)
- typeBind = new ArrayList<>();
+ typeBind = new ArrayList();
String typeBindDef = fieldMap.get("type-bind");
if (typeBindDef != null && typeBindDef.trim().length() > 0) {
String[] types = typeBindDef.split(",");
@@ -611,7 +611,7 @@ public boolean validate(String value) {
if (StringUtils.isNotBlank(value)) {
try {
if (this.pattern != null) {
- if (!this.pattern.matcher(value).matches()) {
+ if (!pattern.matcher(value).matches()) {
return false;
}
}
diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java
index 72051d31e8d8..ac8031880233 100644
--- a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java
+++ b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java
@@ -158,8 +158,8 @@ public List getPairs(String name) {
* Returns the set of DC inputs used for a particular collection, or the default
* set if no inputs defined for the collection
*
- * @param collectionHandle collection
- * @return DC input set
+ * @param collection collection
+ * @return DC input set
* @throws DCInputsReaderException if no default set defined
* @throws ServletException
*/
diff --git a/dspace-api/src/main/java/org/dspace/app/util/RegexPatternUtils.java b/dspace-api/src/main/java/org/dspace/app/util/RegexPatternUtils.java
index 63657aa25daa..578e57fb0909 100644
--- a/dspace-api/src/main/java/org/dspace/app/util/RegexPatternUtils.java
+++ b/dspace-api/src/main/java/org/dspace/app/util/RegexPatternUtils.java
@@ -34,7 +34,9 @@ public class RegexPatternUtils {
/**
* Computes a pattern starting from a regex definition with flags that
- * uses the standard format: /{regex}/{flags}
.
+ * uses the standard format: /{regex}/{flags}
(ECMAScript format).
+ * This method can transform an ECMAScript regex into a java {@code Pattern} object
+ * wich can be used to validate strings.
*
* If regex is null, empty or blank a null {@code Pattern} will be retrieved
* If it's a valid regex, then a non-null {@code Pattern} will be retrieved,
@@ -49,20 +51,21 @@ public static final Pattern computePattern(String regex) throws PatternSyntaxExc
return null;
}
Matcher inputMatcher = PATTERN_REGEX_INPUT_VALIDATOR.matcher(regex);
- Pattern pattern = null;
+ String regexPattern = regex;
+ String regexFlags = "";
if (inputMatcher.matches()) {
- String regexPattern = inputMatcher.group(2);
- String regexFlags =
+ regexPattern =
+ Optional.of(inputMatcher.group(2))
+ .filter(StringUtils::isNotBlank)
+ .orElse(regex);
+ regexFlags =
Optional.ofNullable(inputMatcher.group(3))
- .filter(StringUtils::isNotBlank)
- .map(flags -> String.format(REGEX_FLAGS, flags))
- .orElse("")
- .replaceAll("g", "");
- pattern = Pattern.compile(regexFlags + regexPattern);
- } else {
- pattern = Pattern.compile(regex);
+ .filter(StringUtils::isNotBlank)
+ .map(flags -> String.format(REGEX_FLAGS, flags))
+ .orElse("")
+ .replaceAll("g", "");
}
- return pattern;
+ return Pattern.compile(regexFlags + regexPattern);
}
private RegexPatternUtils() {}
diff --git a/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java b/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java
index 7f29e6d79e52..03d5dc6b7657 100644
--- a/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java
+++ b/dspace-api/src/main/java/org/dspace/app/util/SubmissionStepConfig.java
@@ -11,6 +11,9 @@
import java.util.Map;
import org.apache.commons.lang3.BooleanUtils;
+import org.dspace.content.InProgressSubmission;
+import org.dspace.content.WorkspaceItem;
+import org.hibernate.proxy.HibernateProxyHelper;
/**
* Class representing configuration for a single step within an Item Submission
@@ -179,6 +182,45 @@ public String getVisibilityOutside() {
return visibilityOutside;
}
+ public boolean isHiddenForInProgressSubmission(InProgressSubmission> obj) {
+
+ String scopeToCheck = getScope(obj);
+
+ if (scope == null || scopeToCheck == null) {
+ return false;
+ }
+
+ String visibility = getVisibility();
+ String visibilityOutside = getVisibilityOutside();
+
+ if (scope.equalsIgnoreCase(scopeToCheck)) {
+ return "hidden".equalsIgnoreCase(visibility);
+ } else {
+ return visibilityOutside == null || "hidden".equalsIgnoreCase(visibilityOutside);
+ }
+
+ }
+
+ public boolean isReadOnlyForInProgressSubmission(InProgressSubmission> obj) {
+
+ String scopeToCheck = getScope(obj);
+
+ if (scope == null || scopeToCheck == null) {
+ return false;
+ }
+
+ String visibility = scope.equalsIgnoreCase(scopeToCheck) ? getVisibility() : getVisibilityOutside();
+ return "read-only".equalsIgnoreCase(visibility);
+
+ }
+
+ private String getScope(InProgressSubmission> obj) {
+ if (HibernateProxyHelper.getClassWithoutInitializingProxy(obj).equals(WorkspaceItem.class)) {
+ return "submission";
+ }
+ return "workflow";
+ }
+
/**
* Get the number of this step in the current Submission process config.
* Step numbers start with #0 (although step #0 is ALWAYS the special
diff --git a/dspace-api/src/main/java/org/dspace/authority/service/ItemReferenceResolver.java b/dspace-api/src/main/java/org/dspace/authority/service/ItemReferenceResolver.java
index 3c9a3d40068b..cd80accf9ba1 100644
--- a/dspace-api/src/main/java/org/dspace/authority/service/ItemReferenceResolver.java
+++ b/dspace-api/src/main/java/org/dspace/authority/service/ItemReferenceResolver.java
@@ -24,13 +24,11 @@ public interface ItemReferenceResolver {
*
* @param context the DSpace Context
* @param item the item to search for
- * @return the found items
*/
void resolveReferences(Context context, Item item);
/**
* Clears the resolver cache if any is used
- * @return void
*/
void clearCache();
}
diff --git a/dspace-api/src/main/java/org/dspace/authority/service/ItemReferenceResolverService.java b/dspace-api/src/main/java/org/dspace/authority/service/ItemReferenceResolverService.java
index ba54c01c174d..3f5678185c71 100644
--- a/dspace-api/src/main/java/org/dspace/authority/service/ItemReferenceResolverService.java
+++ b/dspace-api/src/main/java/org/dspace/authority/service/ItemReferenceResolverService.java
@@ -24,13 +24,11 @@ public interface ItemReferenceResolverService {
*
* @param context the DSpace Context
* @param item the item to search for
- * @return the found items
*/
void resolveReferences(Context context, Item item);
/**
* Clears the resolver cache if any is used
- * @return void
*/
void clearResolversCache();
}
diff --git a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java
index 645f703b18f5..014de4671c8b 100644
--- a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java
@@ -35,10 +35,12 @@
import org.dspace.content.RelationshipType;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamService;
+import org.dspace.content.service.CollectionService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.discovery.DiscoverQuery;
+import org.dspace.discovery.DiscoverQuery.SORT_ORDER;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.IndexableObject;
import org.dspace.discovery.SearchService;
@@ -543,6 +545,15 @@ public void inheritPolicies(Context c, DSpaceObject src,
addPolicies(c, nonAdminPolicies, dest);
}
+ @Override
+ public void replaceAllPolicies(Context context, DSpaceObject source, DSpaceObject dest)
+ throws SQLException, AuthorizeException {
+ // find all policies for the source object
+ List policies = getPolicies(context, source);
+ removeAllPolicies(context, dest);
+ addPolicies(context, policies, dest);
+ }
+
@Override
public void switchPoliciesAction(Context context, DSpaceObject dso, int fromAction, int toAction)
throws SQLException, AuthorizeException {
@@ -852,7 +863,7 @@ public List findAdminAuthorizedCommunity(Context context, String quer
query = formatCustomQuery(query);
DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" +
IndexableCommunity.TYPE,
- offset, limit);
+ offset, limit, null, null);
for (IndexableObject solrCollections : discoverResult.getIndexableObjects()) {
Community community = ((IndexableCommunity) solrCollections).getIndexedObject();
communities.add(community);
@@ -874,7 +885,7 @@ public long countAdminAuthorizedCommunity(Context context, String query)
query = formatCustomQuery(query);
DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" +
IndexableCommunity.TYPE,
- null, null);
+ null, null, null, null);
return discoverResult.getTotalSearchResults();
}
@@ -895,11 +906,12 @@ public List findAdminAuthorizedCollection(Context context, String qu
if (context.getCurrentUser() == null) {
return collections;
}
- StringBuilder queryBuilder = new StringBuilder();
- queryBuilder.append(formatCustomQuery(query));
- queryBuilder.append("search.resourcetype:").append(IndexableCollection.TYPE);
- DiscoverResult discoverResult = getDiscoverResult(context, queryBuilder.toString(),
- offset, limit);
+
+ query = formatCustomQuery(query);
+ DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" +
+ IndexableCollection.TYPE,
+ offset, limit, CollectionService.SOLR_SORT_FIELD, SORT_ORDER.asc);
+
for (IndexableObject solrCollections : discoverResult.getIndexableObjects()) {
Collection collection = ((IndexableCollection) solrCollections).getIndexedObject();
collections.add(collection);
@@ -921,7 +933,7 @@ public long countAdminAuthorizedCollection(Context context, String query)
query = formatCustomQuery(query);
DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" +
IndexableCollection.TYPE,
- null, null);
+ null, null, null, null);
return discoverResult.getTotalSearchResults();
}
@@ -941,7 +953,7 @@ private boolean performCheck(Context context, String query) throws SQLException
}
try {
- DiscoverResult discoverResult = getDiscoverResult(context, query, null, null);
+ DiscoverResult discoverResult = getDiscoverResult(context, query, null, null, null, null);
if (discoverResult.getTotalSearchResults() > 0) {
return true;
}
@@ -953,8 +965,8 @@ private boolean performCheck(Context context, String query) throws SQLException
return false;
}
- private DiscoverResult getDiscoverResult(Context context, String query, Integer offset, Integer limit)
- throws SearchServiceException, SQLException {
+ private DiscoverResult getDiscoverResult(Context context, String query, Integer offset, Integer limit,
+ String sortField, SORT_ORDER sortOrder) throws SearchServiceException, SQLException {
DiscoverQuery discoverQuery = new DiscoverQuery();
if (!this.isAdmin(context)) {
StringBuilder stringBuilder = new StringBuilder();
@@ -970,7 +982,9 @@ private DiscoverResult getDiscoverResult(Context context, String query, Integer
if (limit != null) {
discoverQuery.setMaxResults(limit);
}
-
+ if (sortField != null && sortOrder != null) {
+ discoverQuery.setSortField(sortField, sortOrder);
+ }
return searchService.search(context, discoverQuery);
}
diff --git a/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java b/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java
index bf2f74e22313..43ae51544c9b 100644
--- a/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java
+++ b/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java
@@ -644,4 +644,16 @@ long countAdminAuthorizedCollection(Context context, String query)
*/
boolean isAccountManager(Context context);
+ /**
+ * Replace all the policies in the target object with exactly the same policies that exist in the source object
+ *
+ * @param context DSpace Context
+ * @param source source of policies
+ * @param dest destination of inherited policies
+ * @throws SQLException if there's a database problem
+ * @throws AuthorizeException if the current user is not authorized to add these policies
+ */
+ public void replaceAllPolicies(Context context, DSpaceObject source, DSpaceObject dest)
+ throws SQLException, AuthorizeException;
+
}
diff --git a/dspace-api/src/main/java/org/dspace/batch/service/ImpRecordService.java b/dspace-api/src/main/java/org/dspace/batch/service/ImpRecordService.java
index cc22b70fea39..0a07187e3fa1 100644
--- a/dspace-api/src/main/java/org/dspace/batch/service/ImpRecordService.java
+++ b/dspace-api/src/main/java/org/dspace/batch/service/ImpRecordService.java
@@ -59,7 +59,6 @@ public interface ImpRecordService {
* withdrawn state
*
* @param impRecord the ImpRecord object
- * @param ePerson the person
*/
public void setStatus(ImpRecord impRecord, Character status);
@@ -69,7 +68,6 @@ public interface ImpRecordService {
* update = update or create a new record delete = delete the record
*
* @param impRecord the ImpRecord object
- * @param ePerson the person
*/
public void setOperation(ImpRecord impRecord, String operation);
diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/BrowseDAO.java
index 29debf64e2af..03130e39e78b 100644
--- a/dspace-api/src/main/java/org/dspace/browse/BrowseDAO.java
+++ b/dspace-api/src/main/java/org/dspace/browse/BrowseDAO.java
@@ -8,8 +8,8 @@
package org.dspace.browse;
import java.util.List;
-import java.util.UUID;
+import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
/**
@@ -140,21 +140,21 @@ public interface BrowseDAO {
public void setAscending(boolean ascending);
/**
- * Get the database ID of the container object. The container object will be a
+ * Get the container object. The container object will be a
* Community or a Collection.
*
- * @return the database id of the container, or -1 if none is set
+ * @return the container, or null if none is set
*/
- public UUID getContainerID();
+ public DSpaceObject getContainer();
/**
- * Set the database id of the container object. This should be the id of a
- * Community or Collection. This will constrain the results of the browse
- * to only items or values within items that appear in the given container.
+ * Set the container object. This should be a Community or Collection.
+ * This will constrain the results of the browse to only items or values within items that appear in the given
+ * container and add the related configuration default filters.
*
- * @param containerID community/collection internal ID (UUID)
+ * @param container community/collection
*/
- public void setContainerID(UUID containerID);
+ public void setContainer(DSpaceObject container);
/**
* get the name of the field in which to look for the container id. This is
diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java b/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java
index 6f0235e6c156..351c36248209 100644
--- a/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java
+++ b/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java
@@ -141,12 +141,12 @@ public BrowseInfo browseMini(BrowserScope bs)
Collection col = (Collection) scope.getBrowseContainer();
dao.setContainerTable("collection2item");
dao.setContainerIDField("collection_id");
- dao.setContainerID(col.getID());
+ dao.setContainer(col);
} else if (scope.inCommunity()) {
Community com = (Community) scope.getBrowseContainer();
dao.setContainerTable("communities2item");
dao.setContainerIDField("community_id");
- dao.setContainerID(com.getID());
+ dao.setContainer(com);
}
}
@@ -247,12 +247,12 @@ private BrowseInfo browseByItem(BrowserScope bs)
Collection col = (Collection) scope.getBrowseContainer();
dao.setContainerTable("collection2item");
dao.setContainerIDField("collection_id");
- dao.setContainerID(col.getID());
+ dao.setContainer(col);
} else if (scope.inCommunity()) {
Community com = (Community) scope.getBrowseContainer();
dao.setContainerTable("communities2item");
dao.setContainerIDField("community_id");
- dao.setContainerID(com.getID());
+ dao.setContainer(com);
}
}
@@ -413,12 +413,12 @@ private BrowseInfo browseByValue(BrowserScope bs)
Collection col = (Collection) scope.getBrowseContainer();
dao.setContainerTable("collection2item");
dao.setContainerIDField("collection_id");
- dao.setContainerID(col.getID());
+ dao.setContainer(col);
} else if (scope.inCommunity()) {
Community com = (Community) scope.getBrowseContainer();
dao.setContainerTable("communities2item");
dao.setContainerIDField("community_id");
- dao.setContainerID(com.getID());
+ dao.setContainer(com);
}
}
diff --git a/dspace-api/src/main/java/org/dspace/browse/CrossLinks.java b/dspace-api/src/main/java/org/dspace/browse/CrossLinks.java
index aa30862e3c34..1ce2e558866d 100644
--- a/dspace-api/src/main/java/org/dspace/browse/CrossLinks.java
+++ b/dspace-api/src/main/java/org/dspace/browse/CrossLinks.java
@@ -59,7 +59,16 @@ public CrossLinks()
* @return true/false
*/
public boolean hasLink(String metadata) {
- return links.containsKey(metadata);
+ return findLinkType(metadata) != null;
+ }
+
+ /**
+ * Is there a link for the given browse name (eg 'author')
+ * @param browseIndexName
+ * @return true/false
+ */
+ public boolean hasBrowseName(String browseIndexName) {
+ return links.containsValue(browseIndexName);
}
/**
@@ -69,6 +78,41 @@ public boolean hasLink(String metadata) {
* @return type
*/
public String getLinkType(String metadata) {
- return links.get(metadata);
+ return findLinkType(metadata);
+ }
+
+ /**
+ * Get full map of field->indexname link configurations
+ * @return
+ */
+ public Map getLinks() {
+ return links;
+ }
+
+ /**
+ * Find and return the browse name for a given metadata field.
+ * If the link key contains a wildcard eg dc.subject.*, it should
+ * match dc.subject.other, etc.
+ * @param metadata
+ * @return
+ */
+ public String findLinkType(String metadata) {
+ // Resolve wildcards properly, eg. dc.subject.other matches a configuration for dc.subject.*
+ for (String key : links.keySet()) {
+ if (null != key && key.endsWith(".*")) {
+ // A substring of length-1, also substracting the wildcard should work as a "startsWith"
+ // check for the field eg. dc.subject.* -> dc.subject is the start of dc.subject.other
+ if (null != metadata && metadata.startsWith(key.substring(0, key.length() - 1 - ".*".length()))) {
+ return links.get(key);
+ }
+ } else {
+ // Exact match, if the key field has no .* wildcard
+ if (links.containsKey(metadata)) {
+ return links.get(key);
+ }
+ }
+ }
+ // No match
+ return null;
}
}
diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java
index e48486d86c04..0194be59f3a7 100644
--- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java
+++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java
@@ -13,12 +13,13 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
+import org.apache.solr.client.solrj.util.ClientUtils;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.AuthorizeService;
+import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.discovery.DiscoverFacetField;
@@ -30,6 +31,8 @@
import org.dspace.discovery.IndexableObject;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
+import org.dspace.discovery.SearchUtils;
+import org.dspace.discovery.configuration.DiscoveryConfiguration;
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
import org.dspace.discovery.indexobject.IndexableItem;
import org.dspace.services.ConfigurationService;
@@ -124,9 +127,9 @@ public int compare(Object o1, Object o2) {
private String containerIDField = null;
/**
- * the database id of the container we are constraining to
+ * the container we are constraining to
*/
- private UUID containerID = null;
+ private DSpaceObject container = null;
/**
* the column that we are sorting results by
@@ -180,6 +183,7 @@ private DiscoverResult getSolrResponse() throws BrowseException {
addLocationScopeFilter(query);
addStatusFilter(query);
addExtraFilter(query);
+ addDefaultFilterQueries(query);
if (distinct) {
DiscoverFacetField dff;
if (StringUtils.isNotBlank(startsWith)) {
@@ -210,7 +214,8 @@ private DiscoverResult getSolrResponse() throws BrowseException {
query.addFilterQueries("{!field f=" + facetField + "_partial}" + value);
}
if (StringUtils.isNotBlank(startsWith) && orderField != null) {
- query.addFilterQueries("bi_" + orderField + "_sort:" + startsWith + "*");
+ query.addFilterQueries(
+ "bi_" + orderField + "_sort:" + ClientUtils.escapeQueryChars(startsWith) + "*");
}
// filter on item to be sure to don't include any other object
// indexed in the Discovery Search core
@@ -249,15 +254,20 @@ private void addStatusFilter(DiscoverQuery query) {
}
private void addLocationScopeFilter(DiscoverQuery query) {
- if (containerID != null) {
+ if (container != null) {
if (containerIDField.startsWith("collection")) {
- query.addFilterQueries("location.coll:" + containerID);
+ query.addFilterQueries("location.coll:" + container.getID());
} else if (containerIDField.startsWith("community")) {
- query.addFilterQueries("location.comm:" + containerID);
+ query.addFilterQueries("location.comm:" + container.getID());
}
}
}
+ private void addDefaultFilterQueries(DiscoverQuery query) {
+ DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(container);
+ discoveryConfiguration.getDefaultFilterQueries().forEach(query::addFilterQueries);
+ }
+
@Override
public int doCountQuery() throws BrowseException {
DiscoverResult resp = getSolrResponse();
@@ -348,6 +358,7 @@ public int doOffsetQuery(String column, String value, boolean isAscending)
addLocationScopeFilter(query);
addStatusFilter(query);
addExtraFilter(query);
+ addDefaultFilterQueries(query);
query.setMaxResults(0);
query.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE);
@@ -408,8 +419,8 @@ public void setEnableBrowseFrequencies(boolean enableBrowseFrequencies) {
* @see org.dspace.browse.BrowseDAO#getContainerID()
*/
@Override
- public UUID getContainerID() {
- return containerID;
+ public DSpaceObject getContainer() {
+ return container;
}
/*
@@ -571,8 +582,8 @@ public void setAscending(boolean ascending) {
* @see org.dspace.browse.BrowseDAO#setContainerID(int)
*/
@Override
- public void setContainerID(UUID containerID) {
- this.containerID = containerID;
+ public void setContainer(DSpaceObject container) {
+ this.container = container;
}
diff --git a/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java
index 3df762e5423d..367c7a5d34b1 100644
--- a/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java
@@ -48,6 +48,7 @@
import org.dspace.core.LogHelper;
import org.dspace.core.service.LicenseService;
import org.dspace.discovery.DiscoverQuery;
+import org.dspace.discovery.DiscoverQuery.SORT_ORDER;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.IndexableObject;
import org.dspace.discovery.SearchService;
@@ -961,8 +962,8 @@ public List findCollectionsWithSubmit(String q, Context context, Com
discoverQuery.setDSpaceObjectFilter(IndexableCollection.TYPE);
discoverQuery.setStart(offset);
discoverQuery.setMaxResults(limit);
- DiscoverResult resp = retrieveCollectionsWithSubmit(context, discoverQuery,
- entityType, community, q);
+ discoverQuery.setSortField(SOLR_SORT_FIELD, SORT_ORDER.asc);
+ DiscoverResult resp = retrieveCollectionsWithSubmit(context, discoverQuery, entityType, community, q);
for (IndexableObject solrCollections : resp.getIndexableObjects()) {
Collection c = ((IndexableCollection) solrCollections).getIndexedObject();
collections.add(c);
diff --git a/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java
index c1284c6dfd58..b4053a724f32 100644
--- a/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java
@@ -79,6 +79,7 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl imp
protected SubscribeService subscribeService;
@Autowired(required = true)
protected CrisMetricsService crisMetricsService;
+
protected CommunityServiceImpl() {
super();
@@ -554,6 +555,8 @@ protected void rawDelete(Context context, Community community)
context.addEvent(new Event(Event.DELETE, Constants.COMMUNITY, community.getID(), community.getHandle(),
getIdentifiers(context, community)));
+ subscribeService.deleteByDspaceObject(context, community);
+
// Remove collections
Iterator collections = community.getCollections().iterator();
diff --git a/dspace-api/src/main/java/org/dspace/content/InstallItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/InstallItemServiceImpl.java
index 360fc20cadf4..213bbcbaa0cc 100644
--- a/dspace-api/src/main/java/org/dspace/content/InstallItemServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/InstallItemServiceImpl.java
@@ -10,10 +10,15 @@
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
+import java.util.Map;
import org.apache.commons.lang.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.factory.ContentServiceFactory;
+import org.dspace.content.logic.Filter;
+import org.dspace.content.logic.FilterUtils;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService;
@@ -21,8 +26,11 @@
import org.dspace.core.Context;
import org.dspace.embargo.service.EmbargoService;
import org.dspace.event.Event;
+import org.dspace.identifier.Identifier;
import org.dspace.identifier.IdentifierException;
import org.dspace.identifier.service.IdentifierService;
+import org.dspace.supervision.SupervisionOrder;
+import org.dspace.supervision.service.SupervisionOrderService;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -43,9 +51,13 @@ public class InstallItemServiceImpl implements InstallItemService {
protected IdentifierService identifierService;
@Autowired(required = true)
protected ItemService itemService;
+ @Autowired(required = true)
+ protected SupervisionOrderService supervisionOrderService;
+ @Autowired(required = false)
- protected InstallItemServiceImpl() {
+ Logger log = LogManager.getLogger(InstallItemServiceImpl.class);
+ protected InstallItemServiceImpl() {
}
@Override
@@ -60,10 +72,14 @@ public Item installItem(Context c, InProgressSubmission is,
AuthorizeException {
Item item = is.getItem();
Collection collection = is.getCollection();
+ // Get map of filters to use for identifier types.
+ Map, Filter> filters = FilterUtils.getIdentifierFilters(false);
try {
if (suppliedHandle == null) {
- identifierService.register(c, item);
+ // Register with the filters we've set up
+ identifierService.register(c, item, filters);
} else {
+ // This will register the handle but a pending DOI won't be compatible and so won't be registered
identifierService.register(c, item, suppliedHandle);
}
} catch (IdentifierException e) {
@@ -224,9 +240,19 @@ protected Item finishItem(Context c, Item item, InProgressSubmission is)
// set embargo lift date and take away read access if indicated.
embargoService.setEmbargo(c, item);
+ // delete all related supervision orders
+ deleteSupervisionOrders(c, item);
+
return item;
}
+ private void deleteSupervisionOrders(Context c, Item item) throws SQLException, AuthorizeException {
+ List supervisionOrders = supervisionOrderService.findByItem(c, item);
+ for (SupervisionOrder supervisionOrder : supervisionOrders) {
+ supervisionOrderService.delete(c, supervisionOrder);
+ }
+ }
+
@Override
public String getBitstreamProvenanceMessage(Context context, Item myitem)
throws SQLException {
diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java
index 99bd3252149d..3ad03377cb27 100644
--- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java
@@ -31,11 +31,14 @@
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.app.metrics.service.CrisMetricsService;
+import org.dspace.app.requestitem.RequestItem;
+import org.dspace.app.requestitem.service.RequestItemService;
import org.dspace.app.util.AuthorizeUtil;
import org.dspace.authority.service.impl.ItemSearcherByMetadata;
import org.dspace.authorize.AuthorizeConfiguration;
@@ -62,12 +65,16 @@
import org.dspace.core.LogHelper;
import org.dspace.core.exception.SQLRuntimeException;
import org.dspace.discovery.DiscoverQuery;
+import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.DiscoverResultItemIterator;
+import org.dspace.discovery.SearchService;
+import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.indexobject.IndexableItem;
import org.dspace.discovery.indexobject.IndexableWorkflowItem;
import org.dspace.discovery.indexobject.IndexableWorkspaceItem;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
+import org.dspace.eperson.service.GroupService;
import org.dspace.eperson.service.SubscribeService;
import org.dspace.event.Event;
import org.dspace.harvest.HarvestedItem;
@@ -117,6 +124,8 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl- implements It
@Autowired(required = true)
protected CommunityService communityService;
@Autowired(required = true)
+ protected GroupService groupService;
+ @Autowired(required = true)
protected AuthorizeService authorizeService;
@Autowired(required = true)
protected BundleService bundleService;
@@ -129,6 +138,8 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl
- implements It
@Autowired(required = true)
protected InstallItemService installItemService;
@Autowired(required = true)
+ protected SearchService searchService;
+ @Autowired(required = true)
protected ResourcePolicyService resourcePolicyService;
@Autowired(required = true)
protected CollectionService collectionService;
@@ -181,6 +192,8 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl
- implements It
@Autowired(required = true)
private ResearcherProfileService researcherProfileService;
+ @Autowired(required = true)
+ private RequestItemService requestItemService;
@Autowired
private VersionHistoryService versionHistoryService;
@@ -952,6 +965,8 @@ protected void rawDelete(Context context, Item item) throws AuthorizeException,
// remove version attached to the item
removeVersion(context, item);
+ removeRequest(context, item);
+
removeOrcidSynchronizationStuff(context, item);
// Also delete the item if it appears in a harvested collection.
@@ -1076,6 +1091,14 @@ private Optional getBusinesIdentifier(Item item) {
return Optional.empty();
}
+ protected void removeRequest(Context context, Item item) throws SQLException {
+ Iterator requestItems = requestItemService.findByItem(context, item);
+ while (requestItems.hasNext()) {
+ RequestItem requestItem = requestItems.next();
+ requestItemService.delete(context, requestItem);
+ }
+ }
+
@Override
public void removeAllBundles(Context context, Item item) throws AuthorizeException, SQLException, IOException {
Iterator bundles = item.getBundles().iterator();
@@ -1353,6 +1376,53 @@ public boolean canEdit(Context context, Item item) throws SQLException {
return collectionService.canEditBoolean(context, item.getOwningCollection(), false);
}
+ /**
+ * Finds all Indexed Items where the current user has edit rights. If the user is an Admin,
+ * this is all Indexed Items. Otherwise, it includes those Items where
+ * an indexed "edit" policy lists either the eperson or one of the eperson's groups
+ *
+ * @param context DSpace context
+ * @param discoverQuery
+ * @return discovery search result objects
+ * @throws SQLException if something goes wrong
+ * @throws SearchServiceException if search error
+ */
+ private DiscoverResult retrieveItemsWithEdit(Context context, DiscoverQuery discoverQuery)
+ throws SQLException, SearchServiceException {
+ EPerson currentUser = context.getCurrentUser();
+ if (!authorizeService.isAdmin(context)) {
+ String userId = currentUser != null ? "e" + currentUser.getID().toString() : "e";
+ Stream groupIds = groupService.allMemberGroupsSet(context, currentUser).stream()
+ .map(group -> "g" + group.getID());
+ String query = Stream.concat(Stream.of(userId), groupIds)
+ .collect(Collectors.joining(" OR ", "edit:(", ")"));
+ discoverQuery.addFilterQueries(query);
+ }
+ return searchService.search(context, discoverQuery);
+ }
+
+ @Override
+ public List
- findItemsWithEdit(Context context, int offset, int limit)
+ throws SQLException, SearchServiceException {
+ DiscoverQuery discoverQuery = new DiscoverQuery();
+ discoverQuery.setDSpaceObjectFilter(IndexableItem.TYPE);
+ discoverQuery.setStart(offset);
+ discoverQuery.setMaxResults(limit);
+ DiscoverResult resp = retrieveItemsWithEdit(context, discoverQuery);
+ return resp.getIndexableObjects().stream()
+ .map(solrItems -> ((IndexableItem) solrItems).getIndexedObject())
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public int countItemsWithEdit(Context context) throws SQLException, SearchServiceException {
+ DiscoverQuery discoverQuery = new DiscoverQuery();
+ discoverQuery.setMaxResults(0);
+ discoverQuery.setDSpaceObjectFilter(IndexableItem.TYPE);
+ DiscoverResult resp = retrieveItemsWithEdit(context, discoverQuery);
+ return (int) resp.getTotalSearchResults();
+ }
+
/**
* Check if the item is an inprogress submission
*
diff --git a/dspace-api/src/main/java/org/dspace/content/SupervisedItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/SupervisedItemServiceImpl.java
deleted file mode 100644
index b0eb77ec2aa8..000000000000
--- a/dspace-api/src/main/java/org/dspace/content/SupervisedItemServiceImpl.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * The contents of this file are subject to the license and copyright
- * detailed in the LICENSE and NOTICE files at the root of the source
- * tree and available online at
- *
- * http://www.dspace.org/license/
- */
-package org.dspace.content;
-
-import java.sql.SQLException;
-import java.util.List;
-
-import org.dspace.content.service.SupervisedItemService;
-import org.dspace.content.service.WorkspaceItemService;
-import org.dspace.core.Context;
-import org.dspace.eperson.EPerson;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public class SupervisedItemServiceImpl implements SupervisedItemService {
-
- @Autowired(required = true)
- protected WorkspaceItemService workspaceItemService;
-
- protected SupervisedItemServiceImpl() {
-
- }
-
- @Override
- public List getAll(Context context)
- throws SQLException {
- return workspaceItemService.findAllSupervisedItems(context);
- }
-
- @Override
- public List findbyEPerson(Context context, EPerson ep)
- throws SQLException {
- return workspaceItemService.findSupervisedItemsByEPerson(context, ep);
- }
-
-}
diff --git a/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java b/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java
index d512637180ad..37e5bb056ff4 100644
--- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java
+++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java
@@ -8,8 +8,6 @@
package org.dspace.content;
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -17,8 +15,6 @@
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
@@ -27,7 +23,6 @@
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
-import org.dspace.eperson.Group;
import org.dspace.workflow.WorkflowItem;
import org.hibernate.proxy.HibernateProxyHelper;
@@ -78,14 +73,6 @@ public class WorkspaceItem
@Column(name = "page_reached")
private Integer pageReached = -1;
- @ManyToMany(fetch = FetchType.LAZY)
- @JoinTable(
- name = "epersongroup2workspaceitem",
- joinColumns = {@JoinColumn(name = "workspace_item_id")},
- inverseJoinColumns = {@JoinColumn(name = "eperson_group_id")}
- )
- private final List supervisorGroups = new ArrayList<>();
-
/**
* Protected constructor, create object using:
* {@link org.dspace.content.service.WorkspaceItemService#create(Context, Collection, boolean)}
@@ -226,15 +213,4 @@ public void setPublishedBefore(boolean b) {
publishedBefore = b;
}
- public List getSupervisorGroups() {
- return supervisorGroups;
- }
-
- void removeSupervisorGroup(Group group) {
- supervisorGroups.remove(group);
- }
-
- void addSupervisorGroup(Group group) {
- supervisorGroups.add(group);
- }
}
diff --git a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java
index 34f02968b33e..f1a8e546ebb1 100644
--- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java
@@ -24,6 +24,8 @@
import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.dao.WorkspaceItemDAO;
+import org.dspace.content.logic.Filter;
+import org.dspace.content.logic.FilterUtils;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.MetadataFieldService;
@@ -37,6 +39,13 @@
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.event.Event;
+import org.dspace.identifier.DOI;
+import org.dspace.identifier.DOIIdentifierProvider;
+import org.dspace.identifier.Identifier;
+import org.dspace.identifier.IdentifierException;
+import org.dspace.identifier.factory.IdentifierServiceFactory;
+import org.dspace.identifier.service.DOIService;
+import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.workflow.WorkflowItem;
import org.dspace.workflow.WorkflowService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -63,6 +72,7 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
protected ItemService itemService;
@Autowired(required = true)
protected WorkflowService workflowService;
+
@Autowired
private MetadataFieldService metadataFieldService;
@Autowired
@@ -70,6 +80,10 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
@Autowired
private TemplateItemValueService templateItemValueService;
+ @Autowired(required = true)
+ protected DOIService doiService;
+
+
protected WorkspaceItemServiceImpl() {
}
@@ -174,6 +188,26 @@ public WorkspaceItem create(Context context, Collection collection, UUID uuid, b
}
itemService.update(context, item);
+
+ // If configured, register identifiers (eg handle, DOI) now. This is typically used with the Show Identifiers
+ // submission step which previews minted handles and DOIs during the submission process. Default: false
+ if (DSpaceServicesFactory.getInstance().getConfigurationService()
+ .getBooleanProperty("identifiers.submission.register", false)) {
+ try {
+ // Get map of filters to use for identifier types, while the item is in progress
+ Map, Filter> filters = FilterUtils.getIdentifierFilters(true);
+ IdentifierServiceFactory.getInstance().getIdentifierService().register(context, item, filters);
+ // Look for a DOI and move it to PENDING
+ DOI doi = doiService.findDOIByDSpaceObject(context, item);
+ if (doi != null) {
+ doi.setStatus(DOIIdentifierProvider.PENDING);
+ doiService.update(context, doi);
+ }
+ } catch (IdentifierException e) {
+ log.error("Could not register identifier(s) for item {}: {}", item.getID(), e.getMessage());
+ }
+ }
+
workspaceItem.setItem(item);
log.info(LogHelper.getHeader(context, "create_workspace_item",
@@ -226,16 +260,6 @@ public WorkspaceItem findByItem(Context context, Item item) throws SQLException
return workspaceItemDAO.findByItem(context, item);
}
- @Override
- public List findAllSupervisedItems(Context context) throws SQLException {
- return workspaceItemDAO.findWithSupervisedGroup(context);
- }
-
- @Override
- public List findSupervisedItemsByEPerson(Context context, EPerson ePerson) throws SQLException {
- return workspaceItemDAO.findBySupervisedGroupMember(context, ePerson);
- }
-
@Override
public List findAll(Context context) throws SQLException {
return workspaceItemDAO.findAll(context);
@@ -274,10 +298,6 @@ public void deleteAll(Context context, WorkspaceItem workspaceItem)
"workspace_item_id=" + workspaceItem.getID() + "item_id=" + item.getID()
+ "collection_id=" + workspaceItem.getCollection().getID()));
- // Need to delete the epersongroup2workspaceitem row first since it refers
- // to workspaceitem ID
- workspaceItem.getSupervisorGroups().clear();
-
// Need to delete the workspaceitem row first since it refers
// to item ID
workspaceItemDAO.delete(context, workspaceItem);
@@ -313,14 +333,6 @@ public void deleteWrapper(Context context, WorkspaceItem workspaceItem) throws S
// deleteSubmitPermissions();
- // Need to delete the workspaceitem row first since it refers
- // to item ID
- try {
- workspaceItem.getSupervisorGroups().clear();
- } catch (Exception e) {
- log.error("failed to clear supervisor group", e);
- }
-
workspaceItemDAO.delete(context, workspaceItem);
}
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/CustomAuthoritySolrFilter.java b/dspace-api/src/main/java/org/dspace/content/authority/CustomAuthoritySolrFilter.java
index 7b63f4f733db..ef8c09d2569e 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/CustomAuthoritySolrFilter.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/CustomAuthoritySolrFilter.java
@@ -22,7 +22,6 @@ public interface CustomAuthoritySolrFilter {
/**
* Get the confidence value for the generated choices
- * @param searchTerm The search term string
* @return solr query
*/
public int getConfidenceForChoices(Choice... choices);
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java
index 3928dae3abec..cfd8c53f79ad 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java
@@ -152,7 +152,9 @@ private synchronized void init() {
}
protected String buildString(Node node) {
- if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ if (node.getNodeType() == Node.DOCUMENT_NODE || (
+ node.getParentNode() != null &&
+ node.getParentNode().getNodeType() == Node.DOCUMENT_NODE)) {
return ("");
} else {
String parentValue = buildString(node.getParentNode());
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/PersonStrictCustomSolrFilterImpl.java b/dspace-api/src/main/java/org/dspace/content/authority/PersonStrictCustomSolrFilterImpl.java
index f8332311fe60..9a52db998af9 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/PersonStrictCustomSolrFilterImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/PersonStrictCustomSolrFilterImpl.java
@@ -10,6 +10,8 @@
import static org.apache.solr.client.solrj.util.ClientUtils.escapeQueryChars;
import static org.dspace.discovery.SolrServiceStrictBestMatchIndexingPlugin.cleanNameWithStrictPolicies;
+import java.util.Optional;
+
import org.dspace.discovery.SolrServiceStrictBestMatchIndexingPlugin;
/**
@@ -29,8 +31,9 @@ public String getSolrQuery(String searchTerm) {
* @return solr query
*/
public String generateSearchQueryStrictBestMatch(String searchTerm) {
- return SolrServiceStrictBestMatchIndexingPlugin.BEST_MATCH_INDEX + ":"
- + escapeQueryChars(cleanNameWithStrictPolicies(searchTerm));
+ return Optional.ofNullable(cleanNameWithStrictPolicies(searchTerm))
+ .map(query -> SolrServiceStrictBestMatchIndexingPlugin.BEST_MATCH_INDEX + ":" + escapeQueryChars(query))
+ .orElse(null);
}
@Override
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/service/ChoiceAuthorityService.java b/dspace-api/src/main/java/org/dspace/content/authority/service/ChoiceAuthorityService.java
index f03da1896b8b..5d91327b8c8f 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/service/ChoiceAuthorityService.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/service/ChoiceAuthorityService.java
@@ -188,7 +188,6 @@ public Choices getBestMatch(String fieldKey, String query, int dsoType, Collecti
/**
* Get the entity type starting from the metadata field.
*
- * @param field single string identifying metadata field
* @return the entity type as a String
*/
String getLinkedEntityType(String fieldKey);
diff --git a/dspace-api/src/main/java/org/dspace/content/authority/service/ItemAuthorityService.java b/dspace-api/src/main/java/org/dspace/content/authority/service/ItemAuthorityService.java
index 976fd07e8ccc..6d81c005c4ef 100644
--- a/dspace-api/src/main/java/org/dspace/content/authority/service/ItemAuthorityService.java
+++ b/dspace-api/src/main/java/org/dspace/content/authority/service/ItemAuthorityService.java
@@ -32,7 +32,6 @@ public interface ItemAuthorityService {
/**
* Get the confidence value for the generated choices
- * @param searchTerm The search term string
* @return solr query
*/
public int getConfidenceForChoices(Choice... choices);
diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/SubscriptionDsoMetadataForEmailCompose.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/SubscriptionDsoMetadataForEmailCompose.java
index 0484b0e82ce1..05fda2b97475 100644
--- a/dspace-api/src/main/java/org/dspace/content/crosswalk/SubscriptionDsoMetadataForEmailCompose.java
+++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/SubscriptionDsoMetadataForEmailCompose.java
@@ -7,15 +7,15 @@
*/
package org.dspace.content.crosswalk;
-import java.io.IOException;
+import static org.dspace.content.Item.ANY;
+
import java.io.OutputStream;
import java.io.PrintStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
-import org.apache.logging.log4j.Logger;
-import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
@@ -24,53 +24,40 @@
import org.dspace.handle.factory.HandleServiceFactory;
import org.springframework.beans.factory.annotation.Autowired;
-
-
/**
* Creates a String to be sent as email body for subscriptions
*
- * @author Alba Aliu at (atis.al)
+ * @author Alba Aliu
*/
public class SubscriptionDsoMetadataForEmailCompose implements StreamDisseminationCrosswalk {
- /**
- * log4j logger
- */
- private static Logger log =
- org.apache.logging.log4j.LogManager.getLogger(SubscriptionDsoMetadataForEmailCompose.class);
private List metadata = new ArrayList<>();
+
@Autowired
private ItemService itemService;
@Override
public boolean canDisseminate(Context context, DSpaceObject dso) {
- try {
- return dso.getType() == Constants.ITEM;
- } catch (Exception e) {
- log.error("Failed getting mail body", e);
- return false;
- }
+ return Objects.nonNull(dso) && dso.getType() == Constants.ITEM;
}
@Override
- public void disseminate(Context context, DSpaceObject dso, OutputStream out)
- throws CrosswalkException, IOException, SQLException, AuthorizeException {
+ public void disseminate(Context context, DSpaceObject dso, OutputStream out) throws SQLException {
if (dso.getType() == Constants.ITEM) {
Item item = (Item) dso;
PrintStream printStream = new PrintStream(out);
- for (int i = 0; i < metadata.size(); i++) {
- String actualMetadata = metadata.get(i);
+ for (String actualMetadata : metadata) {
String[] splitted = actualMetadata.split("\\.");
String qualifier = null;
if (splitted.length == 1) {
qualifier = splitted[2];
}
- String metadataValue = itemService.getMetadataFirstValue(item, splitted[0],
- splitted[1], qualifier, Item.ANY);
+ var metadataValue = itemService.getMetadataFirstValue(item, splitted[0], splitted[1], qualifier, ANY);
printStream.print(metadataValue + " ");
}
- String itemURL = HandleServiceFactory.getInstance().getHandleService()
- .resolveToURL(context, item.getHandle());
+ String itemURL = HandleServiceFactory.getInstance()
+ .getHandleService()
+ .resolveToURL(context, item.getHandle());
printStream.print(itemURL);
printStream.print("\n");
printStream.close();
diff --git a/dspace-api/src/main/java/org/dspace/content/dao/WorkspaceItemDAO.java b/dspace-api/src/main/java/org/dspace/content/dao/WorkspaceItemDAO.java
index 4ae8dc620b21..900858b72869 100644
--- a/dspace-api/src/main/java/org/dspace/content/dao/WorkspaceItemDAO.java
+++ b/dspace-api/src/main/java/org/dspace/content/dao/WorkspaceItemDAO.java
@@ -41,10 +41,6 @@ public List findByEPerson(Context context, EPerson ep, Integer li
public List findAll(Context context, Integer limit, Integer offset) throws SQLException;
- public List findWithSupervisedGroup(Context context) throws SQLException;
-
- public List findBySupervisedGroupMember(Context context, EPerson ePerson) throws SQLException;
-
int countRows(Context context) throws SQLException;
List> getStageReachedCounts(Context context) throws SQLException;
diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/WorkspaceItemDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/WorkspaceItemDAOImpl.java
index de1b9a5aea9e..138451365522 100644
--- a/dspace-api/src/main/java/org/dspace/content/dao/impl/WorkspaceItemDAOImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/WorkspaceItemDAOImpl.java
@@ -15,7 +15,6 @@
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;
import org.dspace.content.Collection;
@@ -26,8 +25,6 @@
import org.dspace.core.AbstractHibernateDAO;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
-import org.dspace.eperson.EPerson_;
-import org.dspace.eperson.Group;
/**
* Hibernate implementation of the Database Access Object interface class for the WorkspaceItem object.
@@ -114,33 +111,6 @@ public List findAll(Context context, Integer limit, Integer offse
return list(context, criteriaQuery, false, WorkspaceItem.class, limit, offset);
}
- @Override
- public List findWithSupervisedGroup(Context context) throws SQLException {
- CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
- CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, WorkspaceItem.class);
- Root workspaceItemRoot = criteriaQuery.from(WorkspaceItem.class);
- criteriaQuery.select(workspaceItemRoot);
- criteriaQuery.where(criteriaBuilder.isNotEmpty(workspaceItemRoot.get(WorkspaceItem_.supervisorGroups)));
-
- List orderList = new LinkedList<>();
- orderList.add(criteriaBuilder.asc(workspaceItemRoot.get(WorkspaceItem_.workspaceItemId)));
- criteriaQuery.orderBy(orderList);
- return list(context, criteriaQuery, false, WorkspaceItem.class, -1, -1);
- }
-
- @Override
- public List findBySupervisedGroupMember(Context context, EPerson ePerson) throws SQLException {
- CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
- CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, WorkspaceItem.class);
- Root workspaceItemRoot = criteriaQuery.from(WorkspaceItem.class);
- Join join = workspaceItemRoot.join("supervisorGroups");
- Join secondJoin = join.join("epeople");
- criteriaQuery.select(workspaceItemRoot);
- criteriaQuery.where(criteriaBuilder.equal(secondJoin.get(EPerson_.id), ePerson.getID()));
- criteriaQuery.orderBy(criteriaBuilder.asc(workspaceItemRoot.get(WorkspaceItem_.workspaceItemId)));
- return list(context, criteriaQuery, false, WorkspaceItem.class, -1, -1);
- }
-
@Override
public int countRows(Context context) throws SQLException {
return count(createQuery(context, "SELECT count(*) from WorkspaceItem"));
diff --git a/dspace-api/src/main/java/org/dspace/content/edit/service/EditItemModeService.java b/dspace-api/src/main/java/org/dspace/content/edit/service/EditItemModeService.java
index 1555300d38a3..915bf9256af7 100644
--- a/dspace-api/src/main/java/org/dspace/content/edit/service/EditItemModeService.java
+++ b/dspace-api/src/main/java/org/dspace/content/edit/service/EditItemModeService.java
@@ -43,7 +43,6 @@ public interface EditItemModeService {
/**
* Finds an edit mode by item and edit name, returns null if not exists
* @param context DSpace context
- * @param itemId UUID Item
* @param name edit mode name
* @return
* @throws SQLException
diff --git a/dspace-api/src/main/java/org/dspace/content/enhancer/impl/RelatedEntityItemEnhancer.java b/dspace-api/src/main/java/org/dspace/content/enhancer/impl/RelatedEntityItemEnhancer.java
index a5d95582e41d..a6c97cc84e65 100644
--- a/dspace-api/src/main/java/org/dspace/content/enhancer/impl/RelatedEntityItemEnhancer.java
+++ b/dspace-api/src/main/java/org/dspace/content/enhancer/impl/RelatedEntityItemEnhancer.java
@@ -78,7 +78,7 @@ private void cleanObsoleteVirtualFields(Context context, Item item) throws SQLEx
}
private void updateVirtualFieldsPlaces(Context context, Item item) {
- List virtualSourceFields = getMetadataValues(item, getVirtualSourceMetadataField());
+ List virtualSourceFields = getVirtualSourceFields(item);
for (MetadataValue virtualSourceField : virtualSourceFields) {
metadataWithPlaceToUpdate(item, virtualSourceField)
.ifPresent(updatePlaces(item, virtualSourceField));
@@ -113,9 +113,9 @@ private List getObsoleteVirtualFields(Item item) {
List obsoleteVirtualFields = new ArrayList<>();
- List virtualSourceFields = getMetadataValues(item, getVirtualSourceMetadataField());
+ List virtualSourceFields = getVirtualSourceFields(item);
for (MetadataValue virtualSourceField : virtualSourceFields) {
- if (isRelatedSourceNoMorePresent(item, virtualSourceField)) {
+ if (!isPlaceholder(virtualSourceField) && isRelatedSourceNoMorePresent(item, virtualSourceField)) {
obsoleteVirtualFields.add(virtualSourceField);
getRelatedVirtualField(item, virtualSourceField).ifPresent(obsoleteVirtualFields::add);
}
@@ -131,7 +131,7 @@ private boolean isRelatedSourceNoMorePresent(Item item, MetadataValue virtualSou
}
private Optional getRelatedVirtualField(Item item, MetadataValue virtualSourceField) {
- return getMetadataValues(item, getVirtualMetadataField()).stream()
+ return getVirtualFields(item).stream()
.filter(metadataValue -> metadataValue.getPlace() == virtualSourceField.getPlace())
.findFirst();
}
@@ -141,6 +141,7 @@ private void performEnhancement(Context context, Item item) throws SQLException
if (noEnhanceableMetadata(context, item)) {
return;
}
+
for (MetadataValue metadataValue : getEnhanceableMetadataValue(item)) {
if (wasValueAlreadyUsedForEnhancement(item, metadataValue)) {
@@ -191,9 +192,19 @@ private List getEnhanceableMetadataValue(Item item) {
}
private boolean wasValueAlreadyUsedForEnhancement(Item item, MetadataValue metadataValue) {
- return getMetadataValues(item, getVirtualSourceMetadataField()).stream()
+
+ if (isPlaceholderAtPlace(getVirtualFields(item), metadataValue.getPlace())) {
+ return true;
+ }
+
+ return getVirtualSourceFields(item).stream()
.anyMatch(virtualSourceField -> virtualSourceField.getPlace() == metadataValue.getPlace()
&& hasAuthorityEqualsTo(metadataValue, virtualSourceField.getValue()));
+
+ }
+
+ private boolean isPlaceholderAtPlace(List metadataValues, int place) {
+ return place < metadataValues.size() ? isPlaceholder(metadataValues.get(place)) : false;
}
private boolean hasAuthorityEqualsTo(MetadataValue metadataValue, String authority) {
@@ -209,10 +220,22 @@ private Item findRelatedEntityItem(Context context, MetadataValue metadataValue)
}
}
+ private boolean isPlaceholder(MetadataValue metadataValue) {
+ return PLACEHOLDER_PARENT_METADATA_VALUE.equals(metadataValue.getValue());
+ }
+
private List getMetadataValues(Item item, String metadataField) {
return itemService.getMetadataByMetadataString(item, metadataField);
}
+ private List getVirtualSourceFields(Item item) {
+ return getMetadataValues(item, getVirtualSourceMetadataField());
+ }
+
+ private List getVirtualFields(Item item) {
+ return getMetadataValues(item, getVirtualMetadataField());
+ }
+
private void addVirtualField(Context context, Item item, String value) throws SQLException {
itemService.addMetadata(context, item, VIRTUAL_METADATA_SCHEMA, VIRTUAL_METADATA_ELEMENT,
getVirtualQualifier(), null, value);
diff --git a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java
index 2335af007ff2..0b06b34038e1 100644
--- a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java
+++ b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java
@@ -31,7 +31,6 @@
import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.content.service.SiteService;
-import org.dspace.content.service.SupervisedItemService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.eperson.service.SubscribeService;
import org.dspace.services.factory.DSpaceServicesFactory;
@@ -72,8 +71,6 @@ public abstract class ContentServiceFactory {
public abstract InstallItemService getInstallItemService();
- public abstract SupervisedItemService getSupervisedItemService();
-
public abstract SiteService getSiteService();
public abstract SubscribeService getSubscribeService();
@@ -117,11 +114,7 @@ public InProgressSubmissionService getInProgressSubmissionService(InProgressSubm
}
public DSpaceObjectService getDSpaceObjectService(T dso) {
- // No need to worry when supressing, as long as our "getDSpaceObjectManager" method is properly implemented
- // no casting issues should occur
- @SuppressWarnings("unchecked")
- DSpaceObjectService manager = getDSpaceObjectService(dso.getType());
- return manager;
+ return getDSpaceObjectService(dso.getType());
}
@SuppressWarnings("unchecked")
diff --git a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java
index 2a13243e9884..564ec052bcb2 100644
--- a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java
@@ -28,7 +28,6 @@
import org.dspace.content.service.RelationshipService;
import org.dspace.content.service.RelationshipTypeService;
import org.dspace.content.service.SiteService;
-import org.dspace.content.service.SupervisedItemService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.eperson.service.SubscribeService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -69,8 +68,6 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory {
@Autowired(required = true)
private InstallItemService installItemService;
@Autowired(required = true)
- private SupervisedItemService supervisedItemService;
- @Autowired(required = true)
private SiteService siteService;
@Autowired(required = true)
private SubscribeService subscribeService;
@@ -150,15 +147,11 @@ public InstallItemService getInstallItemService() {
return installItemService;
}
- @Override
- public SupervisedItemService getSupervisedItemService() {
- return supervisedItemService;
- }
-
@Override
public SiteService getSiteService() {
return siteService;
}
+
@Override
public SubscribeService getSubscribeService() {
return subscribeService ;
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/DefaultFilter.java b/dspace-api/src/main/java/org/dspace/content/logic/DefaultFilter.java
index e0f88a7a1b72..e17f9bb7c761 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/DefaultFilter.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/DefaultFilter.java
@@ -18,10 +18,10 @@
* statement as a property (unlike an operator) and takes no parameters (unlike a condition)
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class DefaultFilter implements Filter {
private LogicalStatement statement;
+ private String name;
private final static Logger log = LogManager.getLogger();
/**
@@ -44,4 +44,15 @@ public void setStatement(LogicalStatement statement) {
public Boolean getResult(Context context, Item item) throws LogicalStatementException {
return this.statement.getResult(context, item);
}
+
+ @Override
+ public void setBeanName(String name) {
+ log.debug("Initialize bean " + name);
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
}
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/Filter.java b/dspace-api/src/main/java/org/dspace/content/logic/Filter.java
index e156529651f8..70fce036e6cd 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/Filter.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/Filter.java
@@ -9,6 +9,7 @@
import org.dspace.content.Item;
import org.dspace.core.Context;
+import org.springframework.beans.factory.BeanNameAware;
/**
* The interface for Filter currently doesn't add anything to LogicalStatement but inherits from it
@@ -23,7 +24,7 @@
* @version $Revision$
* @see org.dspace.content.logic.DefaultFilter
*/
-public interface Filter extends LogicalStatement {
+public interface Filter extends LogicalStatement, BeanNameAware {
/**
* Get the result of logical evaluation for an item
* @param context DSpace context
@@ -31,5 +32,13 @@ public interface Filter extends LogicalStatement {
* @return boolean
* @throws LogicalStatementException
*/
+ @Override
Boolean getResult(Context context, Item item) throws LogicalStatementException;
+
+ /**
+ * Get the name of a filter. This can be used by filters which make use of BeanNameAware
+ * to return the bean name.
+ * @return the id/name of this spring bean
+ */
+ String getName();
}
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/FilterUtils.java b/dspace-api/src/main/java/org/dspace/content/logic/FilterUtils.java
new file mode 100644
index 000000000000..a878d69e6ed8
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/content/logic/FilterUtils.java
@@ -0,0 +1,85 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.content.logic;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.dspace.identifier.DOI;
+import org.dspace.identifier.Handle;
+import org.dspace.identifier.Identifier;
+import org.dspace.services.ConfigurationService;
+import org.dspace.services.factory.DSpaceServicesFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * General utility methods for logical item filtering
+ *
+ * @author Kim Shepherd
+ */
+public class FilterUtils {
+
+ @Autowired(required = true)
+ ConfigurationService configurationService;
+
+ /**
+ * Get a Filter by configuration property name
+ * For example, if a module has implemented "my-feature.filter" configuration property
+ * this method will return a filter with the ID specified by the configuration property
+ * @param property DSpace configuration property name (Apache Commons config)
+ * @return Filter object, with a bean ID configured for this property key, or null
+ */
+ public static Filter getFilterFromConfiguration(String property) {
+ String filterName = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty(property);
+ if (filterName != null) {
+ return DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(filterName, Filter.class);
+ }
+ return null;
+ }
+
+ /**
+ * Get a Filter by configuration property name
+ * For example, if a module has implemented "my-feature.filter" configuration property
+ * this method will return a filter with the ID specified by the configuration property
+ * @param property DSpace configuration property name (Apache Commons config)
+ * @return Filter object, with a bean ID configured for this property key, or default filter
+ */
+ public static Filter getFilterFromConfiguration(String property, Filter defaultFilter) {
+ Filter filter = getFilterFromConfiguration(property);
+ if (filter != null) {
+ return filter;
+ }
+ return defaultFilter;
+ }
+
+ /**
+ * Get a map of identifier types and filters to use when creating workspace or archived items
+ * This is used by services installing new archived or workspace items to filter by identifier type
+ * as some filters should apply to DOI creation but not Handle creation, and so on.
+ * The in progress or archived status will be used to load the appropriate filter from configuration
+ *
+ * @param inProgress
+ * @return
+ */
+ public static Map, Filter> getIdentifierFilters(boolean inProgress) {
+ String configurationSuffix = "install";
+ if (inProgress) {
+ configurationSuffix = "workspace";
+ }
+ Map, Filter> filters = new HashMap<>();
+ // Put DOI 'can we create DOI on install / workspace?' filter
+ Filter filter = FilterUtils.getFilterFromConfiguration("identifiers.submission.filter." + configurationSuffix);
+ // A null filter should be handled safely by the identifier provier (default, or "always true")
+ filters.put(DOI.class, filter);
+ // This won't have an affect until handle providers implement filtering, but is an example of
+ // how the filters can be used for other types
+ filters.put(Handle.class, DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
+ "always_true_filter", TrueFilter.class));
+ return filters;
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/LogicalStatement.java b/dspace-api/src/main/java/org/dspace/content/logic/LogicalStatement.java
index 38c1e298ee02..004a072eb91a 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/LogicalStatement.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/LogicalStatement.java
@@ -17,7 +17,6 @@
* used as sub-statements in other Filters and Operators.
*
* @author Kim Shepherd
- * @version $Revision$
*/
public interface LogicalStatement {
/**
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/LogicalStatementException.java b/dspace-api/src/main/java/org/dspace/content/logic/LogicalStatementException.java
index 5478a8acdb2e..9898a06b7ade 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/LogicalStatementException.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/LogicalStatementException.java
@@ -12,7 +12,6 @@
* defined as spring beans.
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class LogicalStatementException extends RuntimeException {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/TestLogicRunner.java b/dspace-api/src/main/java/org/dspace/content/logic/TestLogicRunner.java
index b78de7f1902b..bf218eaa8a0f 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/TestLogicRunner.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/TestLogicRunner.java
@@ -33,7 +33,6 @@
* A command-line runner used for testing a logical filter against an item, or all items
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class TestLogicRunner {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/TrueFilter.java b/dspace-api/src/main/java/org/dspace/content/logic/TrueFilter.java
new file mode 100644
index 000000000000..d7d3022e5106
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/content/logic/TrueFilter.java
@@ -0,0 +1,41 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.content.logic;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.dspace.content.Item;
+import org.dspace.core.Context;
+
+/**
+ * Extremely simple filter that always returns true!
+ * Useful to pass to methods that expect a filter, in order to effectively say "all items".
+ * This could be configured in Spring XML but it is more stable and reliable to have it hard-coded here
+ * so that any broken configuration doesn't silently break parts of DSpace that expect it to work.
+ *
+ * @author Kim Shepherd
+ */
+public class TrueFilter implements Filter {
+ private String name;
+ private final static Logger log = LogManager.getLogger();
+
+ public Boolean getResult(Context context, Item item) throws LogicalStatementException {
+ return true;
+ }
+
+ @Override
+ public void setBeanName(String name) {
+ log.debug("Initialize bean " + name);
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/AbstractCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/AbstractCondition.java
index 6cd4f0f910d7..04f7db336dc4 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/AbstractCondition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/AbstractCondition.java
@@ -24,7 +24,6 @@
* Abstract class for conditions, to implement the basic getter and setter parameters
*
* @author Kim Shepherd
- * @version $Revision$
*/
public abstract class AbstractCondition implements Condition {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/BitstreamCountCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/BitstreamCountCondition.java
index dcb57c389ee9..65e26747584a 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/BitstreamCountCondition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/BitstreamCountCondition.java
@@ -18,7 +18,6 @@
* A condition to evaluate an item based on how many bitstreams it has in a particular bundle
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class BitstreamCountCondition extends AbstractCondition {
/**
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/Condition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/Condition.java
index c097263b030e..9c19a0b82dcd 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/Condition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/Condition.java
@@ -22,7 +22,6 @@
* operator is not a condition but also a logical statement.
*
* @author Kim Shepherd
- * @version $Revision$
*/
public interface Condition extends LogicalStatement {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/InCollectionCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/InCollectionCondition.java
index 195dd7064fc1..c2a9258bd895 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/InCollectionCondition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/InCollectionCondition.java
@@ -23,7 +23,6 @@
* if the item belongs to any of them.
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class InCollectionCondition extends AbstractCondition {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/InCommunityCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/InCommunityCondition.java
index cebab799ba16..3be8aeed56c8 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/InCommunityCondition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/InCommunityCondition.java
@@ -24,7 +24,6 @@
* if the item belongs to any of them.
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class InCommunityCondition extends AbstractCondition {
private final static Logger log = LogManager.getLogger();
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/IsArchivedCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/IsArchivedCondition.java
new file mode 100644
index 000000000000..1ae36db08078
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/IsArchivedCondition.java
@@ -0,0 +1,37 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.content.logic.condition;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.dspace.content.Item;
+import org.dspace.content.logic.LogicalStatementException;
+import org.dspace.core.Context;
+
+/**
+ * A condition that returns true if the item is archived
+ *
+ * @author Kim Shepherd
+ */
+public class IsArchivedCondition extends AbstractCondition {
+ private final static Logger log = LogManager.getLogger();
+
+ /**
+ * Return true if item is archived
+ * Return false if not
+ * @param context DSpace context
+ * @param item Item to evaluate
+ * @return boolean result of evaluation
+ * @throws LogicalStatementException
+ */
+ @Override
+ public Boolean getResult(Context context, Item item) throws LogicalStatementException {
+ log.debug("Result of isArchived is " + item.isArchived());
+ return item.isArchived();
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/IsWithdrawnCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/IsWithdrawnCondition.java
index b696c8484885..16f130d43832 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/IsWithdrawnCondition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/IsWithdrawnCondition.java
@@ -17,7 +17,6 @@
* A condition that returns true if the item is withdrawn
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class IsWithdrawnCondition extends AbstractCondition {
private final static Logger log = LogManager.getLogger();
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/MetadataValueMatchCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/MetadataValueMatchCondition.java
index 992d332345d8..6b7db5c1a960 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/MetadataValueMatchCondition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/MetadataValueMatchCondition.java
@@ -23,7 +23,6 @@
* in a given metadata field
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class MetadataValueMatchCondition extends AbstractCondition {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/MetadataValuesMatchCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/MetadataValuesMatchCondition.java
index a5d97c615f13..b58a8c277103 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/MetadataValuesMatchCondition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/MetadataValuesMatchCondition.java
@@ -23,7 +23,6 @@
* in a given metadata field
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class MetadataValuesMatchCondition extends AbstractCondition {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/condition/ReadableByGroupCondition.java b/dspace-api/src/main/java/org/dspace/content/logic/condition/ReadableByGroupCondition.java
index 69699ebfaf1f..09107e8e55dc 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/condition/ReadableByGroupCondition.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/condition/ReadableByGroupCondition.java
@@ -25,7 +25,6 @@
* can perform the action on a given item
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class ReadableByGroupCondition extends AbstractCondition {
private final static Logger log = LogManager.getLogger();
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/operator/AbstractOperator.java b/dspace-api/src/main/java/org/dspace/content/logic/operator/AbstractOperator.java
index 826eb99a8870..f42ca4cf6139 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/operator/AbstractOperator.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/operator/AbstractOperator.java
@@ -22,7 +22,6 @@
* as a logical result
*
* @author Kim Shepherd
- * @version $Revision$
*/
public abstract class AbstractOperator implements LogicalStatement {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/operator/And.java b/dspace-api/src/main/java/org/dspace/content/logic/operator/And.java
index cdc4b8b86dbe..25f4162893b4 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/operator/And.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/operator/And.java
@@ -19,7 +19,6 @@
* true if all sub-statements return true
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class And extends AbstractOperator {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/operator/Nand.java b/dspace-api/src/main/java/org/dspace/content/logic/operator/Nand.java
index 8d1cec727e8b..d95a20e347e4 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/operator/Nand.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/operator/Nand.java
@@ -18,7 +18,6 @@
* An operator that implements NAND by negating an AND operation
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class Nand extends AbstractOperator {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/operator/Not.java b/dspace-api/src/main/java/org/dspace/content/logic/operator/Not.java
index 8d6a076c306d..476ae2c93921 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/operator/Not.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/operator/Not.java
@@ -19,7 +19,6 @@
* Not can have one sub-statement only, while and, or, nor, ... can have multiple sub-statements.
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class Not implements LogicalStatement {
diff --git a/dspace-api/src/main/java/org/dspace/content/logic/operator/Or.java b/dspace-api/src/main/java/org/dspace/content/logic/operator/Or.java
index 7943f094104d..ac4792dc8da0 100644
--- a/dspace-api/src/main/java/org/dspace/content/logic/operator/Or.java
+++ b/dspace-api/src/main/java/org/dspace/content/logic/operator/Or.java
@@ -19,7 +19,6 @@
* true if one or more sub-statements return true
*
* @author Kim Shepherd
- * @version $Revision$
*/
public class Or extends AbstractOperator {
diff --git a/dspace-api/src/main/java/org/dspace/content/security/CrisSecurityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/security/CrisSecurityServiceImpl.java
index 572cf1eec26c..4a8b2c313846 100644
--- a/dspace-api/src/main/java/org/dspace/content/security/CrisSecurityServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/content/security/CrisSecurityServiceImpl.java
@@ -176,16 +176,6 @@ private boolean hasAccessByGroup(Context context, EPerson user, List gro
return false;
}
- try {
- for (Group group : context.getSpecialGroups()) {
- if (groupService.isMember(context, user, group)) {
- return true;
- }
- }
- } catch (SQLException e) {
- throw new SQLRuntimeException(e.getMessage(), e);
- }
-
List userGroups = user.getGroups();
if (CollectionUtils.isEmpty(userGroups)) {
return false;
@@ -194,7 +184,23 @@ private boolean hasAccessByGroup(Context context, EPerson user, List gro
return groups.stream()
.map(group -> findGroupByNameOrUUID(context, group))
.filter(group -> Objects.nonNull(group))
- .anyMatch(group -> userGroups.contains(group));
+ .anyMatch(group -> userGroups.contains(group) || isSpecialGroup(context, group));
+ }
+
+ private boolean isSpecialGroup(Context context, Group group) {
+ return findInSpecialGroups(context, group) != null;
+ }
+
+ private Group findInSpecialGroups(Context context, Group group) {
+ try {
+ return context.getSpecialGroups()
+ .stream()
+ .filter(specialGroup -> specialGroup != null && specialGroup.equals(group))
+ .findFirst()
+ .orElse(null);
+ } catch (SQLException e) {
+ throw new SQLRuntimeException(e.getMessage(), e);
+ }
}
private Group findGroupByNameOrUUID(Context context, String group) {
diff --git a/dspace-api/src/main/java/org/dspace/content/security/service/MetadataSecurityService.java b/dspace-api/src/main/java/org/dspace/content/security/service/MetadataSecurityService.java
index fbcf48b44825..7b03f6464032 100644
--- a/dspace-api/src/main/java/org/dspace/content/security/service/MetadataSecurityService.java
+++ b/dspace-api/src/main/java/org/dspace/content/security/service/MetadataSecurityService.java
@@ -92,8 +92,6 @@ List getPermissionFilteredMetadataValues(Context context, Item it
* @param context the DSpace Context
* @param item the item
* @param metadataField the metadata field
- * @param preventBoxSecurityCheck true if the box security check must be
- * skipped, false otherwise
* @return true if the metadata field is visible, false
* otherwise
*/
diff --git a/dspace-api/src/main/java/org/dspace/content/service/CollectionService.java b/dspace-api/src/main/java/org/dspace/content/service/CollectionService.java
index ba9b665a5a0b..6ce376908bf7 100644
--- a/dspace-api/src/main/java/org/dspace/content/service/CollectionService.java
+++ b/dspace-api/src/main/java/org/dspace/content/service/CollectionService.java
@@ -33,6 +33,11 @@
public interface CollectionService
extends DSpaceObjectService, DSpaceObjectLegacySupportService {
+ /*
+ * Field used to sort community and collection lists at solr
+ */
+ public static final String SOLR_SORT_FIELD = "dc.title_sort";
+
/**
* Create a new collection with a new ID.
* Once created the collection is added to the given community
@@ -46,7 +51,6 @@ public interface CollectionService
public Collection create(Context context, Community community) throws SQLException,
AuthorizeException;
-
/**
* Create a new collection with the supplied handle and with a new ID.
* Once created the collection is added to the given community
diff --git a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java
index 9b15b640c935..e6823690743d 100644
--- a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java
+++ b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java
@@ -29,6 +29,7 @@
import org.dspace.content.Thumbnail;
import org.dspace.content.WorkspaceItem;
import org.dspace.core.Context;
+import org.dspace.discovery.SearchServiceException;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
@@ -753,6 +754,27 @@ public Iterator- findByLastModifiedSince(Context context, Date last)
*/
int countWithdrawnItems(Context context) throws SQLException;
+ /**
+ * finds all items for which the current user has editing rights
+ * @param context DSpace context object
+ * @param offset page offset
+ * @param limit page size limit
+ * @return list of items for which the current user has editing rights
+ * @throws SQLException
+ * @throws SearchServiceException
+ */
+ public List
- findItemsWithEdit(Context context, int offset, int limit)
+ throws SQLException, SearchServiceException;
+
+ /**
+ * counts all items for which the current user has editing rights
+ * @param context DSpace context object
+ * @return list of items for which the current user has editing rights
+ * @throws SQLException
+ * @throws SearchServiceException
+ */
+ public int countItemsWithEdit(Context context) throws SQLException, SearchServiceException;
+
/**
* Check if the supplied item is an inprogress submission
*
@@ -815,8 +837,6 @@ public List getMetadata(Item item, String schema, String element,
String lang, boolean enableVirtualMetadata);
/**
-<<<<<<< HEAD
-=======
* Returns the item's entity type, if any.
*
* @param item the item
@@ -833,7 +853,6 @@ public List getMetadata(Item item, String schema, String element,
public void setEntityType(Context context, Item item, String entityType);
/**
->>>>>>> 4science-bitbucket/dspace-cris-7
* Find all the items in the archive or not with a given authority key value in LIKE format.
*
* @param context DSpace context object
diff --git a/dspace-api/src/main/java/org/dspace/content/service/RelationshipService.java b/dspace-api/src/main/java/org/dspace/content/service/RelationshipService.java
index 21bfc71198b0..6afe9f6b488d 100644
--- a/dspace-api/src/main/java/org/dspace/content/service/RelationshipService.java
+++ b/dspace-api/src/main/java/org/dspace/content/service/RelationshipService.java
@@ -511,7 +511,6 @@ int countByTypeName(Context context, String typeName)
* by this relationship to the left and/or right item
* @param context The relevant DSpace context
* @param relationship The relationship to be deleted
- * @param forceBypassValidation A boolean indicating whether we should force by-pass validation
*/
void delete(Context context, Relationship relationship, boolean bypassValidation)
throws SQLException, AuthorizeException;
diff --git a/dspace-api/src/main/java/org/dspace/content/service/SupervisedItemService.java b/dspace-api/src/main/java/org/dspace/content/service/SupervisedItemService.java
deleted file mode 100644
index 883e0f9fd2fb..000000000000
--- a/dspace-api/src/main/java/org/dspace/content/service/SupervisedItemService.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * The contents of this file are subject to the license and copyright
- * detailed in the LICENSE and NOTICE files at the root of the source
- * tree and available online at
- *
- * http://www.dspace.org/license/
- */
-package org.dspace.content.service;
-
-import java.sql.SQLException;
-import java.util.List;
-
-import org.dspace.content.WorkspaceItem;
-import org.dspace.core.Context;
-import org.dspace.eperson.EPerson;
-
-/**
- * Class to handle WorkspaceItems which are being supervised.
- *
- * @author Richard Jones
- * @version $Revision$
- */
-public interface SupervisedItemService {
- /**
- * Get all workspace items which are being supervised
- *
- * @param context the context this object exists in
- * @return array of SupervisedItems
- * @throws SQLException if database error
- */
- public List getAll(Context context) throws SQLException;
-
-
- /**
- * Get items being supervised by given EPerson
- *
- * @param ep the eperson who's items to supervise we want
- * @param context the dspace context
- * @return the items eperson is supervising in an array
- * @throws SQLException if database error
- */
- public List findbyEPerson(Context context, EPerson ep)
- throws SQLException;
-}
diff --git a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java
index 8f572f6108ac..c8df68e43498 100644
--- a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java
+++ b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java
@@ -127,10 +127,6 @@ public List findByCollection(Context context, Collection collecti
public WorkspaceItem findByItem(Context context, Item item)
throws SQLException;
- public List findAllSupervisedItems(Context context) throws SQLException;
-
- public List findSupervisedItemsByEPerson(Context context, EPerson ePerson) throws SQLException;
-
/**
* Get all workspace items in the whole system
*
diff --git a/dspace-api/src/main/java/org/dspace/core/Email.java b/dspace-api/src/main/java/org/dspace/core/Email.java
index 3255f13b70e1..67567ce97f6f 100644
--- a/dspace-api/src/main/java/org/dspace/core/Email.java
+++ b/dspace-api/src/main/java/org/dspace/core/Email.java
@@ -398,7 +398,7 @@ public void send() throws MessagingException, IOException {
for (String headerName : templateHeaders) {
String headerValue = (String) vctx.get(headerName);
if ("subject".equalsIgnoreCase(headerName)) {
- if (null != subject) {
+ if (null != headerValue) {
subject = headerValue;
}
} else if ("charset".equalsIgnoreCase(headerName)) {
diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/RegisterDOI.java b/dspace-api/src/main/java/org/dspace/ctask/general/RegisterDOI.java
index 4e777d70a8b4..0765d7b000d1 100644
--- a/dspace-api/src/main/java/org/dspace/ctask/general/RegisterDOI.java
+++ b/dspace-api/src/main/java/org/dspace/ctask/general/RegisterDOI.java
@@ -13,11 +13,15 @@
import org.apache.logging.log4j.Logger;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
+import org.dspace.content.logic.Filter;
+import org.dspace.content.logic.FilterUtils;
+import org.dspace.content.logic.TrueFilter;
import org.dspace.curate.AbstractCurationTask;
import org.dspace.curate.Curator;
import org.dspace.identifier.DOIIdentifierProvider;
import org.dspace.identifier.IdentifierException;
import org.dspace.identifier.doi.DOIIdentifierNotApplicableException;
+import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.utils.DSpace;
/**
@@ -39,6 +43,7 @@ public class RegisterDOI extends AbstractCurationTask {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(RegisterDOI.class);
// DOI provider
private DOIIdentifierProvider provider;
+ private Filter trueFilter;
/**
* Initialise the curation task and read configuration, instantiate the DOI provider
@@ -46,14 +51,14 @@ public class RegisterDOI extends AbstractCurationTask {
@Override
public void init(Curator curator, String taskId) throws IOException {
super.init(curator, taskId);
- // Get 'skip filter' behaviour from configuration, with a default value of 'true'
- skipFilter = configurationService.getBooleanProperty(PLUGIN_PREFIX + ".skip-filter", true);
// Get distribution behaviour from configuration, with a default value of 'false'
distributed = configurationService.getBooleanProperty(PLUGIN_PREFIX + ".distributed", false);
log.debug("PLUGIN_PREFIX = " + PLUGIN_PREFIX + ", skipFilter = " + skipFilter +
", distributed = " + distributed);
// Instantiate DOI provider singleton
provider = new DSpace().getSingletonService(DOIIdentifierProvider.class);
+ trueFilter = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
+ "always_true_filter", TrueFilter.class);
}
/**
@@ -118,8 +123,9 @@ private String register(Item item) {
String doi = null;
// Attempt DOI registration and report successes and failures
try {
- log.debug("Registering DOI with skipFilter = " + skipFilter);
- doi = provider.register(Curator.curationContext(), item, skipFilter);
+ Filter filter = FilterUtils.getFilterFromConfiguration("identifiers.submission.filter.curation",
+ trueFilter);
+ doi = provider.register(Curator.curationContext(), item, filter);
if (doi != null) {
String message = "New DOI minted in database for item " + item.getHandle() + ": " + doi
+ ". This DOI will be registered online with the DOI provider when the queue is next run";
diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java
index 52dcce03abf8..e11edda0edd6 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java
@@ -7,6 +7,8 @@
*/
package org.dspace.discovery;
+import static org.dspace.discovery.SolrServiceImpl.SOLR_FIELD_SUFFIX_FACET_PREFIXES;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -165,6 +167,9 @@ public List getFacetResult(DiscoverySearchFilterFacet field) {
if (facetValues.size() == 0 && field.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)) {
facetValues = getFacetResult(field.getIndexFieldName() + ".year");
}
+ if (facetValues.isEmpty()) {
+ facetValues = getFacetResult(field.getIndexFieldName() + SOLR_FIELD_SUFFIX_FACET_PREFIXES);
+ }
return ListUtils.emptyIfNull(facetValues);
}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexingUtils.java b/dspace-api/src/main/java/org/dspace/discovery/IndexingUtils.java
new file mode 100644
index 000000000000..8dd02f5d44e0
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/discovery/IndexingUtils.java
@@ -0,0 +1,119 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.discovery;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import org.dspace.authorize.ResourcePolicy;
+import org.dspace.authorize.service.AuthorizeService;
+import org.dspace.content.Collection;
+import org.dspace.content.Community;
+import org.dspace.content.DSpaceObject;
+import org.dspace.content.factory.ContentServiceFactory;
+import org.dspace.core.Context;
+
+/**
+ * Util methods used by indexing.
+ *
+ * @author Koen Pauwels (koen.pauwels at atmire dot com)
+ */
+public class IndexingUtils {
+ private IndexingUtils() {
+ }
+
+ /**
+ * Retrieve all ancestor communities of a given community, with the first one being the given community and the
+ * last one being the root.
+ *
+ *
+ * @param context DSpace context object
+ * @param community Community for which we search the ancestors
+ * @return A list of ancestor communities.
+ * @throws SQLException if database error
+ */
+ static List getAncestorCommunities(Context context, Community community) throws SQLException {
+ ArrayList communities = new ArrayList<>();
+ while (community != null) {
+ communities.add(community);
+ community = (Community) ContentServiceFactory.getInstance().getDSpaceObjectService(community)
+ .getParentObject(context, community);
+ }
+ return communities;
+ }
+
+ /**
+ * Retrieve the ids of all groups that have ADMIN rights to the given community, either directly
+ * (through direct resource policy) or indirectly (through a policy on an ancestor community).
+ *
+ * @param context DSpace context object
+ * @param community Community for which we search the admin group IDs
+ * @return A list of admin group IDs
+ * @throws SQLException if database error
+ */
+ static List findTransitiveAdminGroupIds(Context context, Community community) throws SQLException {
+ return getAncestorCommunities(context, community).stream()
+ .filter(parent -> parent.getAdministrators() != null)
+ .map(parent -> parent.getAdministrators().getID())
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Retrieve the ids of all groups that have ADMIN rights to the given collection, either directly
+ * (through direct resource policy) or indirectly (through a policy on its community, or one of
+ * its ancestor communities).
+ *
+ * @param context DSpace context object
+ * @param collection Collection for which we search the admin group IDs
+ * @return A list of admin group IDs
+ * @throws SQLException if database error
+ */
+ static List findTransitiveAdminGroupIds(Context context, Collection collection) throws SQLException {
+ List ids = new ArrayList<>();
+ if (collection.getAdministrators() != null) {
+ ids.add(collection.getAdministrators().getID());
+ }
+ for (Community community : collection.getCommunities()) {
+ for (UUID id : findTransitiveAdminGroupIds(context, community)) {
+ ids.add(id);
+ }
+ }
+ return ids;
+ }
+
+ /**
+ * Retrieve group and eperson IDs for all groups and eperson who have _any_ of the given authorizations
+ * on the given DSpaceObject. The resulting IDs are prefixed with "e" in the case of an eperson ID, and "g" in the
+ * case of a group ID.
+ *
+ * @param authService The authentication service
+ * @param context DSpace context object
+ * @param obj DSpaceObject for which we search the admin group IDs
+ * @return A stream of admin group IDs as Strings, prefixed with either "e" or "g", depending on whether it is a
+ * group or eperson ID.
+ * @throws SQLException if database error
+ */
+ static List findDirectlyAuthorizedGroupAndEPersonPrefixedIds(
+ AuthorizeService authService, Context context, DSpaceObject obj, int[] authorizations)
+ throws SQLException {
+ ArrayList prefixedIds = new ArrayList<>();
+ for (int auth : authorizations) {
+ for (ResourcePolicy policy : authService.getPoliciesActionFilter(context, obj, auth)) {
+ String prefixedId = policy.getGroup() == null
+ ? "e" + policy.getEPerson().getID()
+ : "g" + policy.getGroup().getID();
+ prefixedIds.add(prefixedId);
+ context.uncacheEntity(policy);
+ }
+ }
+ return prefixedIds;
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SharedWorkspaceSolrIndexPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SharedWorkspaceSolrIndexPlugin.java
index a30edbdf3f16..1e9fd3aa1b4b 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/SharedWorkspaceSolrIndexPlugin.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/SharedWorkspaceSolrIndexPlugin.java
@@ -122,7 +122,7 @@ private void addRead(SolrInputDocument document, Optional subm) {
private Optional findOwner(Context context, Item source) throws SQLException {
List metadata =
- itemService.getMetadata(source, "dspace", "object", "owner", null);
+ itemService.getMetadata(source, "dspace", "object", "owner", Item.ANY);
if (metadata.isEmpty()) {
return Optional.empty();
}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java
index bdd77ef655bb..bcc169a6df9e 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java
@@ -119,6 +119,10 @@ public class SolrServiceImpl implements SearchService, IndexingService {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SolrServiceImpl.class);
+ // Suffix of the solr field used to index the facet/filter so that the facet search can search all word in a
+ // facet by indexing "each word to end of value' partial value
+ public static final String SOLR_FIELD_SUFFIX_FACET_PREFIXES = "_prefix";
+
@Autowired
protected ContentServiceFactory contentServiceFactory;
@Autowired
@@ -923,6 +927,9 @@ protected SolrQuery resolveToSolrQuery(Context context, DiscoverQuery discoveryQ
//Only add facet information if there are any facets
for (DiscoverFacetField facetFieldConfig : facetFields) {
String field = transformFacetField(facetFieldConfig, facetFieldConfig.getField(), false);
+ if (facetFieldConfig.getPrefix() != null) {
+ field = transformPrefixFacetField(facetFieldConfig, facetFieldConfig.getField(), false);
+ }
solrQuery.addFacetField(field);
if (!facetFieldConfig.fillGaps() && !facetFieldConfig.inverseDirection()) {
@@ -1459,7 +1466,31 @@ public String toSortFieldIndex(String metadataField, String type) {
}
}
+ /**
+ * Gets the solr field that contains the facet value split on each word break to the end, so can be searched
+ * on each word in the value, see {@link org.dspace.discovery.indexobject.ItemIndexFactoryImpl
+ * #saveFacetPrefixParts(SolrInputDocument, DiscoverySearchFilter, String, String)}
+ * Ony applicable to facets of type {@link DiscoveryConfigurationParameters.TYPE_TEXT}, otherwise uses the regular
+ * facet filter field
+ */
+ protected String transformPrefixFacetField(DiscoverFacetField facetFieldConfig, String field,
+ boolean removePostfix) {
+ if (facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_TEXT) ||
+ facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)) {
+ if (removePostfix) {
+ return field.substring(0, field.lastIndexOf(SOLR_FIELD_SUFFIX_FACET_PREFIXES));
+ } else {
+ return field + SOLR_FIELD_SUFFIX_FACET_PREFIXES;
+ }
+ } else {
+ return this.transformFacetField(facetFieldConfig, field, removePostfix);
+ }
+ }
+
protected String transformFacetField(DiscoverFacetField facetFieldConfig, String field, boolean removePostfix) {
+ if (field.contains(SOLR_FIELD_SUFFIX_FACET_PREFIXES)) {
+ return this.transformPrefixFacetField(facetFieldConfig, field, removePostfix);
+ }
if (facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_TEXT)) {
if (removePostfix) {
return field.substring(0, field.lastIndexOf("_filter"));
@@ -1511,7 +1542,7 @@ protected String transformDisplayedValue(Context context, String field, String v
if (field.equals("location.comm") || field.equals("location.coll")) {
value = locationToName(context, field, value);
} else if (field.endsWith("_filter") || field.endsWith("_ac")
- || field.endsWith("_acid")) {
+ || field.endsWith("_acid") || field.endsWith(SOLR_FIELD_SUFFIX_FACET_PREFIXES)) {
//We have a filter make sure we split !
String separator = DSpaceServicesFactory.getInstance().getConfigurationService()
.getProperty("discovery.solr.facets.split.char");
@@ -1543,7 +1574,7 @@ protected String transformAuthorityValue(Context context, String field, String v
return value;
}
if (field.endsWith("_filter") || field.endsWith("_ac")
- || field.endsWith("_acid")) {
+ || field.endsWith("_acid") || field.endsWith(SOLR_FIELD_SUFFIX_FACET_PREFIXES)) {
//We have a filter make sure we split !
String separator = DSpaceServicesFactory.getInstance().getConfigurationService()
.getProperty("discovery.solr.facets.split.char");
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexCollectionSubmittersPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexCollectionSubmittersPlugin.java
index 00b70f93d50e..ee93f954a5bd 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexCollectionSubmittersPlugin.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexCollectionSubmittersPlugin.java
@@ -7,16 +7,17 @@
*/
package org.dspace.discovery;
+import static org.dspace.discovery.IndexingUtils.findDirectlyAuthorizedGroupAndEPersonPrefixedIds;
+import static org.dspace.discovery.IndexingUtils.findTransitiveAdminGroupIds;
+
import java.sql.SQLException;
import java.util.List;
+import java.util.UUID;
import org.apache.logging.log4j.Logger;
import org.apache.solr.common.SolrInputDocument;
-import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
-import org.dspace.content.Community;
-import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.LogHelper;
@@ -42,29 +43,21 @@ public void additionalIndex(Context context, IndexableObject idxObj, SolrInputDo
Collection col = ((IndexableCollection) idxObj).getIndexedObject();
if (col != null) {
try {
- String fieldValue = null;
- Community parent = (Community) ContentServiceFactory.getInstance().getDSpaceObjectService(col)
- .getParentObject(context, col);
- while (parent != null) {
- if (parent.getAdministrators() != null) {
- fieldValue = "g" + parent.getAdministrators().getID();
- document.addField("submit", fieldValue);
- }
- parent = (Community) ContentServiceFactory.getInstance().getDSpaceObjectService(parent)
- .getParentObject(context, parent);
+ // Index groups with ADMIN rights on the Collection, on
+ // Communities containing those Collections, and recursively on any Community containing such a
+ // Community.
+ // TODO: Strictly speaking we should also check for epersons who received admin rights directly,
+ // without being part of the admin group. Finding them may be a lot slower though.
+ for (UUID unprefixedId : findTransitiveAdminGroupIds(context, col)) {
+ document.addField("submit", "g" + unprefixedId);
}
- List policies = authorizeService.getPoliciesActionFilter(context,col,Constants.ADD);
- policies.addAll(authorizeService.getPoliciesActionFilter(context, col, Constants.ADMIN));
-
- for (ResourcePolicy resourcePolicy : policies) {
- if (resourcePolicy.getGroup() != null) {
- fieldValue = "g" + resourcePolicy.getGroup().getID();
- } else {
- fieldValue = "e" + resourcePolicy.getEPerson().getID();
- }
- document.addField("submit", fieldValue);
- context.uncacheEntity(resourcePolicy);
+ // Index groups and epersons with ADD or ADMIN rights on the Collection.
+ List prefixedIds = findDirectlyAuthorizedGroupAndEPersonPrefixedIds(
+ authorizeService, context, col, new int[] {Constants.ADD, Constants.ADMIN}
+ );
+ for (String prefixedId : prefixedIds) {
+ document.addField("submit", prefixedId);
}
} catch (SQLException e) {
log.error(LogHelper.getHeader(context, "Error while indexing resource policies",
@@ -73,5 +66,4 @@ public void additionalIndex(Context context, IndexableObject idxObj, SolrInputDo
}
}
}
-
-}
\ No newline at end of file
+}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexItemEditorsPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexItemEditorsPlugin.java
new file mode 100644
index 000000000000..09308be75920
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexItemEditorsPlugin.java
@@ -0,0 +1,71 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.discovery;
+
+import static org.dspace.discovery.IndexingUtils.findDirectlyAuthorizedGroupAndEPersonPrefixedIds;
+import static org.dspace.discovery.IndexingUtils.findTransitiveAdminGroupIds;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.solr.common.SolrInputDocument;
+import org.dspace.authorize.service.AuthorizeService;
+import org.dspace.content.Collection;
+import org.dspace.content.Item;
+import org.dspace.core.Constants;
+import org.dspace.core.Context;
+import org.dspace.core.LogHelper;
+import org.dspace.discovery.indexobject.IndexableItem;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Indexes policies that yield write access to items.
+ *
+ * @author Koen Pauwels at atmire.com
+ */
+public class SolrServiceIndexItemEditorsPlugin implements SolrServiceIndexPlugin {
+ private static final Logger log = org.apache.logging.log4j.LogManager
+ .getLogger(SolrServiceIndexItemEditorsPlugin.class);
+
+ @Autowired(required = true)
+ protected AuthorizeService authorizeService;
+
+ @Override
+ public void additionalIndex(Context context, IndexableObject idxObj, SolrInputDocument document) {
+ if (idxObj instanceof IndexableItem) {
+ Item item = ((IndexableItem) idxObj).getIndexedObject();
+ if (item != null) {
+ try {
+ // Index groups with ADMIN rights on Collections containing the Item, on
+ // Communities containing those Collections, and recursively on any Community containing ssuch a
+ // Community.
+ // TODO: Strictly speaking we should also check for epersons who received admin rights directly,
+ // without being part of the admin group. Finding them may be a lot slower though.
+ for (Collection collection : item.getCollections()) {
+ for (UUID unprefixedId : findTransitiveAdminGroupIds(context, collection)) {
+ document.addField("edit", "g" + unprefixedId);
+ }
+ }
+
+ // Index groups and epersons with WRITE or direct ADMIN rights on the Item.
+ List prefixedIds = findDirectlyAuthorizedGroupAndEPersonPrefixedIds(
+ authorizeService, context, item, new int[] {Constants.WRITE, Constants.ADMIN}
+ );
+ for (String prefixedId : prefixedIds) {
+ document.addField("edit", prefixedId);
+ }
+ } catch (SQLException e) {
+ log.error(LogHelper.getHeader(context, "Error while indexing resource policies",
+ "Item: (id " + item.getID() + " name " + item.getName() + ")" ));
+ }
+ }
+ }
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java
index aa6f0a8c971c..7be7ecff450d 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java
@@ -7,6 +7,8 @@
*/
package org.dspace.discovery;
+import static org.dspace.discovery.SolrServiceImpl.SOLR_FIELD_SUFFIX_FACET_PREFIXES;
+
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -269,9 +271,9 @@ public void additionalIndex(Context context, IndexableObject indexableObject, So
}
}
}
-
for (String facet : distFValues) {
document.addField(bi.getDistinctTableName() + "_filter", facet);
+ document.addField(bi.getDistinctTableName() + SOLR_FIELD_SUFFIX_FACET_PREFIXES, facet);
}
for (String facet : distFAuths) {
document.addField(bi.getDistinctTableName() + "_authority_filter", facet);
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceStrictBestMatchIndexingPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceStrictBestMatchIndexingPlugin.java
index 3ee84ce63642..d3154470a6af 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceStrictBestMatchIndexingPlugin.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceStrictBestMatchIndexingPlugin.java
@@ -7,11 +7,11 @@
*/
package org.dspace.discovery;
-import static java.util.stream.Collectors.toSet;
-
import java.util.Collection;
import java.util.HashSet;
+import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.solr.common.SolrInputDocument;
@@ -67,16 +67,19 @@ public Set getPossibleBestMatchValues(String firstName, String lastName,
}
public Set getPossibleBestMatchValues(Collection fullnames) {
-
- Set nameSet = new HashSet();
- // add all possible matches to the solr index
- nameSet.addAll(fullnames.stream().map(SolrServiceStrictBestMatchIndexingPlugin::cleanNameWithStrictPolicies)
- .collect(toSet()));
-
- return nameSet;
+ return fullnames
+ .stream()
+ .filter(Objects::nonNull)
+ // add all possible matches to the solr index
+ .map(SolrServiceStrictBestMatchIndexingPlugin::cleanNameWithStrictPolicies)
+ .collect(Collectors.toSet());
}
public static String cleanNameWithStrictPolicies(String name) {
+ if (name == null) {
+ return null;
+ }
+
if (configurationService.getBooleanProperty(EXCLUDE_LETTER_CASE_CONFIG, true)) {
name = name.toLowerCase();
}
@@ -110,6 +113,7 @@ private static Set generateBaseNameSet(String firstName, String lastName
return baseNameSet;
}
+ @Override
protected void addIndexValue(SolrInputDocument document, String value) {
document.addField(BEST_MATCH_INDEX, value);
}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSupervisionOrderIndexingPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSupervisionOrderIndexingPlugin.java
new file mode 100644
index 000000000000..116b5ec88d1b
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSupervisionOrderIndexingPlugin.java
@@ -0,0 +1,68 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.discovery;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.solr.common.SolrInputDocument;
+import org.dspace.content.Item;
+import org.dspace.core.Context;
+import org.dspace.discovery.indexobject.IndexableInProgressSubmission;
+import org.dspace.discovery.indexobject.IndexableWorkflowItem;
+import org.dspace.discovery.indexobject.IndexableWorkspaceItem;
+import org.dspace.supervision.SupervisionOrder;
+import org.dspace.supervision.service.SupervisionOrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * A Solr Indexing plugin responsible adding a `supervised` field.
+ * When item being indexed is a workspace or workflow item,
+ * and at least one supervision order is defined
+ * the 'supervised' field with value 'true' will be added to the solr document,
+ * if no supervision orders are defined field will be set to 'false'
+ *
+ * @author Mohamed Eskander (mohamed.eskander at 4science dot it)
+ */
+public class SolrServiceSupervisionOrderIndexingPlugin implements SolrServiceIndexPlugin {
+
+ @Autowired(required = true)
+ private SupervisionOrderService supervisionOrderService;
+
+ @Override
+ public void additionalIndex(Context context, IndexableObject indexableObject, SolrInputDocument document) {
+ try {
+
+ if (!(indexableObject instanceof IndexableWorkspaceItem) &&
+ !(indexableObject instanceof IndexableWorkflowItem)) {
+ return;
+ }
+
+ Item item =
+ (((IndexableInProgressSubmission) indexableObject).getIndexedObject()).getItem();
+
+ if (Objects.isNull(item)) {
+ return;
+ }
+ addSupervisedField(context, item, document);
+ } catch (SQLException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ private void addSupervisedField(Context context, Item item, SolrInputDocument document) throws SQLException {
+ List supervisionOrders = supervisionOrderService.findByItem(context, item);
+ if (CollectionUtils.isNotEmpty(supervisionOrders)) {
+ document.addField("supervised", true);
+ } else {
+ document.addField("supervised", false);
+ }
+ }
+}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceValuePairsIndexPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceValuePairsIndexPlugin.java
index f6ccbabf0c6c..213d6547d958 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceValuePairsIndexPlugin.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceValuePairsIndexPlugin.java
@@ -10,6 +10,7 @@
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.dspace.discovery.SearchUtils.AUTHORITY_SEPARATOR;
import static org.dspace.discovery.SearchUtils.FILTER_SEPARATOR;
+import static org.dspace.discovery.SolrServiceImpl.SOLR_FIELD_SUFFIX_FACET_PREFIXES;
import java.sql.SQLException;
import java.util.List;
@@ -127,10 +128,12 @@ private void addDiscoveryFieldFields(String language, SolrInputDocument document
String keywordField = appendAuthorityIfNotBlank(value, authority);
String acidField = appendAuthorityIfNotBlank(valueLowerCase + separator + value, authority);
String filterField = appendAuthorityIfNotBlank(valueLowerCase + separator + value, authority);
+ String prefixField = appendAuthorityIfNotBlank(valueLowerCase + separator + value, authority);
document.addField(fieldNameWithLanguage + "_keyword", keywordField);
document.addField(fieldNameWithLanguage + "_acid", acidField);
document.addField(fieldNameWithLanguage + "_filter", filterField);
+ document.addField(fieldNameWithLanguage + SOLR_FIELD_SUFFIX_FACET_PREFIXES, prefixField);
document.addField(fieldNameWithLanguage + "_ac", valueLowerCase + separator + value);
if (document.containsKey(searchFilter.getIndexFieldName() + "_authority")) {
document.addField(fieldNameWithLanguage + "_authority", authority);
diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceWorkspaceWorkflowRestrictionPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceWorkspaceWorkflowRestrictionPlugin.java
index fd05be1cb521..161849475651 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceWorkspaceWorkflowRestrictionPlugin.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceWorkspaceWorkflowRestrictionPlugin.java
@@ -40,6 +40,11 @@ public class SolrServiceWorkspaceWorkflowRestrictionPlugin implements SolrServic
*/
public static final String DISCOVER_WORKFLOW_ADMIN_CONFIGURATION_NAME = "workflowAdmin";
+ /**
+ * The name of the discover configuration used by administrators to search for workspace and workflow tasks
+ */
+ public static final String DISCOVER_SUPERVISION_CONFIGURATION_NAME = "supervision";
+
@Autowired(required = true)
protected GroupService groupService;
@@ -60,18 +65,22 @@ public void additionalSearchParameters(
);
boolean isWorkflowAdmin = isAdmin(context)
&& DISCOVER_WORKFLOW_ADMIN_CONFIGURATION_NAME.equals(discoveryQuery.getDiscoveryConfigurationName());
+
+ boolean isSupervision =
+ DISCOVER_SUPERVISION_CONFIGURATION_NAME.equals(discoveryQuery.getDiscoveryConfigurationName());
+
EPerson currentUser = context.getCurrentUser();
// extra security check to avoid the possibility that an anonymous user
// get access to workspace or workflow
- if (currentUser == null && (isWorkflow || isWorkspace)) {
+ if (currentUser == null && (isWorkflow || isWorkspace || isSupervision)) {
throw new IllegalStateException(
"An anonymous user cannot perform a workspace or workflow search");
}
if (isWorkspace) {
// insert filter by submitter
solrQuery.addFilterQuery("submitter_authority:(" + currentUser.getID() + ")");
- } else if (isWorkflow && !isWorkflowAdmin) {
+ } else if ((isWorkflow && !isWorkflowAdmin) || (isSupervision && !isAdmin(context))) {
// Retrieve all the groups the current user is a member of !
Set groups;
try {
diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java
index feaedf2cb5b8..8e9c1a77aeb5 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java
@@ -169,4 +169,5 @@ public List getDiscoveryConfigurationWithPrefixName(fina
}
return discoveryConfigurationList;
}
+
}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryRelatedItemConfiguration.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryRelatedItemConfiguration.java
index d069b9ce1d63..6c24a6bac671 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryRelatedItemConfiguration.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryRelatedItemConfiguration.java
@@ -10,7 +10,7 @@
/**
* This class extends {@link DiscoveryConfiguration} and add method for set parameters
* to filter query list
- * @author Danilo Di Nuzzo (danilo.dinuzzo at 4science.it)
*
+ * @author Danilo Di Nuzzo (danilo.dinuzzo at 4science.it)
*/
-public class DiscoveryRelatedItemConfiguration extends DiscoveryConfiguration {}
+public class DiscoveryRelatedItemConfiguration extends DiscoveryConfiguration {}
\ No newline at end of file
diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortFunctionConfiguration.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortFunctionConfiguration.java
index 074c3d40f9eb..7fb020cd560b 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortFunctionConfiguration.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortFunctionConfiguration.java
@@ -58,9 +58,9 @@ public void setId(final String id) {
* @return
*/
public String getFunction(final Serializable... functionArgs) {
- final String args = String.join(",",
- Optional.ofNullable(arguments).orElse(Collections.emptyList()));
+ final String args = String.join(",", Optional.ofNullable(arguments).orElse(Collections.emptyList()));
final String result = function + "(" + args + ")";
- return MessageFormat.format(result, functionArgs);
+ return MessageFormat.format(result, functionArgs);
}
+
}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java
index d0b0f363e64b..8a24b997ffae 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java
@@ -22,6 +22,8 @@
import org.dspace.discovery.indexobject.factory.InprogressSubmissionIndexFactory;
import org.dspace.discovery.indexobject.factory.ItemIndexFactory;
import org.dspace.eperson.EPerson;
+import org.dspace.supervision.SupervisionOrder;
+import org.dspace.supervision.service.SupervisionOrderService;
import org.dspace.util.SolrUtils;
import org.dspace.workflow.WorkflowItem;
import org.springframework.beans.factory.annotation.Autowired;
@@ -39,6 +41,9 @@ public abstract class InprogressSubmissionIndexFactoryImpl
@Autowired
protected ItemIndexFactory indexableItemService;
+ @Autowired
+ protected SupervisionOrderService supervisionOrderService;
+
@Override
public SolrInputDocument buildDocument(Context context, T indexableObject) throws SQLException, IOException {
@@ -60,6 +65,8 @@ public void storeInprogressItemFields(Context context, SolrInputDocument doc,
submitter.getFullName());
}
+ addSupervisedByFacetIndex(context, item, doc);
+
doc.addField("inprogress.item", new IndexableItem(inProgressSubmission.getItem()).getUniqueIndexID());
// get the location string (for searching by collection & community)
@@ -82,4 +89,13 @@ public void storeInprogressItemFields(Context context, SolrInputDocument doc,
indexableItemService.addDiscoveryFields(doc, context, item, discoveryConfigurations);
indexableCollectionService.storeCommunityCollectionLocations(doc, locations);
}
+
+ private void addSupervisedByFacetIndex(Context context, Item item, SolrInputDocument doc) throws SQLException {
+ List supervisionOrders = supervisionOrderService.findByItem(context, item);
+ for (SupervisionOrder supervisionOrder : supervisionOrders) {
+ addFacetIndex(doc, "supervisedBy", supervisionOrder.getGroup().getID().toString(),
+ supervisionOrder.getGroup().getName());
+ }
+
+ }
}
diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java
index 464c82d8e25f..82247bb972d2 100644
--- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java
+++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java
@@ -7,6 +7,8 @@
*/
package org.dspace.discovery.indexobject;
+import static org.dspace.discovery.SolrServiceImpl.SOLR_FIELD_SUFFIX_FACET_PREFIXES;
+
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
@@ -20,6 +22,8 @@
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
@@ -496,7 +500,7 @@ public void addDiscoveryFields(SolrInputDocument doc, Context context, Item item
+ var);
}
}
-
+ // if searchFilter is of type "facet", delegate to indexIfFilterTypeFacet method
if (searchFilter.getFilterType().equals(DiscoverySearchFilterFacet.FILTER_TYPE_FACET)) {
if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_TEXT)) {
//Add a special filter
@@ -622,6 +626,8 @@ public void addDiscoveryFields(SolrInputDocument doc, Context context, Item item
facetValue.toLowerCase() + separator + facetValue);
}
}
+ indexIfFilterTypeFacet(doc, searchFilter, value, date,
+ authority, preferedLabel, separator);
}
}
}
@@ -822,4 +828,140 @@ public Optional findIndexableObject(Context context, String id) t
final Item item = itemService.find(context, UUID.fromString(id));
return item == null ? Optional.empty() : Optional.of(new IndexableItem(item));
}
+
+ /**
+ * Handles indexing when discoverySearchFilter is of type facet.
+ *
+ * @param doc the solr document
+ * @param searchFilter the discoverySearchFilter
+ * @param value the metadata value
+ * @param date Date object
+ * @param authority the authority key
+ * @param preferedLabel the preferred label for metadata field
+ * @param separator the separator being used to separate lowercase and regular case
+ */
+ private void indexIfFilterTypeFacet(SolrInputDocument doc, DiscoverySearchFilter searchFilter, String value,
+ Date date, String authority, String preferedLabel, String separator) {
+ if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_TEXT)) {
+ //Add a special filter
+ //We use a separator to split up the lowercase and regular case, this is needed to
+ // get our filters in regular case
+ //Solr has issues with facet prefix and cases
+ if (authority != null) {
+ String facetValue = preferedLabel != null ? preferedLabel : value;
+ doc.addField(searchFilter.getIndexFieldName() + "_filter", facetValue
+ .toLowerCase() + separator + facetValue + SearchUtils.AUTHORITY_SEPARATOR
+ + authority);
+ } else {
+ doc.addField(searchFilter.getIndexFieldName() + "_filter",
+ value.toLowerCase() + separator + value);
+ }
+ //Also add prefix field with all parts of value
+ saveFacetPrefixParts(doc, searchFilter, value, separator, authority, preferedLabel);
+ } else if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)) {
+ if (date != null) {
+ String indexField = searchFilter.getIndexFieldName() + ".year";
+ String yearUTC = DateFormatUtils.formatUTC(date, "yyyy");
+ doc.addField(searchFilter.getIndexFieldName() + "_keyword", yearUTC);
+ // add the year to the autocomplete index
+ doc.addField(searchFilter.getIndexFieldName() + "_ac", yearUTC);
+ doc.addField(indexField, yearUTC);
+
+ if (yearUTC.startsWith("0")) {
+ doc.addField(
+ searchFilter.getIndexFieldName()
+ + "_keyword",
+ yearUTC.replaceFirst("0*", ""));
+ // add date without starting zeros for autocomplete e filtering
+ doc.addField(
+ searchFilter.getIndexFieldName()
+ + "_ac",
+ yearUTC.replaceFirst("0*", ""));
+ doc.addField(
+ searchFilter.getIndexFieldName()
+ + "_ac",
+ value.replaceFirst("0*", ""));
+ doc.addField(
+ searchFilter.getIndexFieldName()
+ + "_keyword",
+ value.replaceFirst("0*", ""));
+ }
+
+ //Also save a sort value of this year, this is required for determining the upper
+ // & lower bound year of our facet
+ if (doc.getField(indexField + "_sort") == null) {
+ //We can only add one year so take the first one
+ doc.addField(indexField + "_sort", yearUTC);
+ }
+ }
+ } else if (searchFilter.getType()
+ .equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)) {
+ HierarchicalSidebarFacetConfiguration hierarchicalSidebarFacetConfiguration =
+ (HierarchicalSidebarFacetConfiguration) searchFilter;
+ String[] subValues = value.split(hierarchicalSidebarFacetConfiguration.getSplitter());
+ if (hierarchicalSidebarFacetConfiguration
+ .isSkipFirstNodeLevel() && 1 < subValues.length) {
+ //Remove the first element of our array
+ subValues = (String[]) ArrayUtils.subarray(subValues, 1, subValues.length);
+ }
+ for (int i = 0; i < subValues.length; i++) {
+ StringBuilder valueBuilder = new StringBuilder();
+ for (int j = 0; j <= i; j++) {
+ valueBuilder.append(subValues[j]);
+ if (j < i) {
+ valueBuilder.append(hierarchicalSidebarFacetConfiguration.getSplitter());
+ }
+ }
+
+ String indexValue = valueBuilder.toString().trim();
+ doc.addField(searchFilter.getIndexFieldName() + "_tax_" + i + "_filter",
+ indexValue.toLowerCase() + separator + indexValue);
+ //We add the field x times that it has occurred
+ for (int j = i; j < subValues.length; j++) {
+ doc.addField(searchFilter.getIndexFieldName() + "_filter",
+ indexValue.toLowerCase() + separator + indexValue);
+ doc.addField(searchFilter.getIndexFieldName() + "_keyword", indexValue);
+ }
+ }
+ //Also add prefix field with all parts of value
+ saveFacetPrefixParts(doc, searchFilter, value, separator, authority, preferedLabel);
+ }
+ }
+
+ /**
+ * Stores every "value part" in lowercase, together with the original value in regular case,
+ * separated by the separator, in the {fieldName}{@link SolrServiceImpl.SOLR_FIELD_SUFFIX_FACET_PREFIXES} field.
+ *
+ * E.g. Author "With Multiple Words" gets stored as:
+ *
+ *
+ * with multiple words ||| With Multiple Words,
+ * multiple words ||| With Multiple Words,
+ * words ||| With Multiple Words,
+ *
+ * in the author_prefix field.
+ * @param doc the solr document
+ * @param searchFilter the current discoverySearchFilter
+ * @param value the metadata value
+ * @param separator the separator being used to separate value part and original value
+ */
+ private void saveFacetPrefixParts(SolrInputDocument doc, DiscoverySearchFilter searchFilter, String value,
+ String separator, String authority, String preferedLabel) {
+ value = StringUtils.normalizeSpace(value);
+ Pattern pattern = Pattern.compile("\\b\\w+\\b", Pattern.CASE_INSENSITIVE);
+ Matcher matcher = pattern.matcher(value);
+ while (matcher.find()) {
+ int index = matcher.start();
+ String currentPart = StringUtils.substring(value, index);
+ if (authority != null) {
+ String facetValue = preferedLabel != null ? preferedLabel : currentPart;
+ doc.addField(searchFilter.getIndexFieldName() + SOLR_FIELD_SUFFIX_FACET_PREFIXES,
+ facetValue.toLowerCase() + separator + value
+ + SearchUtils.AUTHORITY_SEPARATOR + authority);
+ } else {
+ doc.addField(searchFilter.getIndexFieldName() + SOLR_FIELD_SUFFIX_FACET_PREFIXES,
+ currentPart.toLowerCase() + separator + value);
+ }
+ }
+ }
}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java
index c54ffa629362..283f101f2ba5 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/AccountServiceImpl.java
@@ -18,6 +18,7 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.dspace.authenticate.service.AuthenticationService;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.Context;
import org.dspace.core.Email;
@@ -59,6 +60,9 @@ public class AccountServiceImpl implements AccountService {
@Autowired
private GroupService groupService;
+ @Autowired
+ private AuthenticationService authenticationService;
+
protected AccountServiceImpl() {
}
@@ -87,6 +91,9 @@ public void sendRegistrationInfo(Context context, String email, List group
if (!configurationService.getBooleanProperty("user.registration", true)) {
throw new IllegalStateException("The user.registration parameter was set to false");
}
+ if (!authenticationService.canSelfRegister(context, null, email)) {
+ throw new IllegalStateException("self registration is not allowed with this email address");
+ }
sendInfo(context, email, groups, true, true);
}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/FrequencyType.java b/dspace-api/src/main/java/org/dspace/eperson/FrequencyType.java
new file mode 100644
index 000000000000..72822fb8716e
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/eperson/FrequencyType.java
@@ -0,0 +1,81 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.eperson;
+
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+
+import org.apache.commons.codec.binary.StringUtils;
+
+/**
+ * This enum holds all the possible frequency types
+ * that can be used in "subscription-send" script
+ *
+ * @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
+ */
+public enum FrequencyType {
+ DAY("D"),
+ WEEK("W"),
+ MONTH("M");
+
+ private String shortName;
+
+ private FrequencyType(String shortName) {
+ this.shortName = shortName;
+ }
+
+ public static String findLastFrequency(String frequency) {
+ String startDate = "";
+ String endDate = "";
+ Calendar cal = Calendar.getInstance();
+ // Full ISO 8601 is e.g.
+ SimpleDateFormat fullIsoStart = new SimpleDateFormat("yyyy-MM-dd'T'00:00:00'Z'");
+ SimpleDateFormat fullIsoEnd = new SimpleDateFormat("yyyy-MM-dd'T'23:59:59'Z'");
+ switch (frequency) {
+ case "D":
+ cal.add(Calendar.DAY_OF_MONTH, -1);
+ endDate = fullIsoEnd.format(cal.getTime());
+ startDate = fullIsoStart.format(cal.getTime());
+ break;
+ case "M":
+ int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
+ cal.add(Calendar.DAY_OF_MONTH, -dayOfMonth);
+ endDate = fullIsoEnd.format(cal.getTime());
+ cal.add(Calendar.MONTH, -1);
+ cal.add(Calendar.DAY_OF_MONTH, 1);
+ startDate = fullIsoStart.format(cal.getTime());
+ break;
+ case "W":
+ cal.add(Calendar.DAY_OF_WEEK, -1);
+ int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;
+ cal.add(Calendar.DAY_OF_WEEK, -dayOfWeek);
+ endDate = fullIsoEnd.format(cal.getTime());
+ cal.add(Calendar.DAY_OF_WEEK, -6);
+ startDate = fullIsoStart.format(cal.getTime());
+ break;
+ default:
+ return null;
+ }
+ return "[" + startDate + " TO " + endDate + "]";
+ }
+
+ public static boolean isSupportedFrequencyType(String value) {
+ for (FrequencyType ft : Arrays.asList(FrequencyType.values())) {
+ if (StringUtils.equals(ft.getShortName(), value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String getShortName() {
+ return shortName;
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/Group.java b/dspace-api/src/main/java/org/dspace/eperson/Group.java
index 15b0cede7382..8fe4f94f9647 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/Group.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/Group.java
@@ -23,7 +23,6 @@
import org.apache.commons.lang3.StringUtils;
import org.dspace.content.DSpaceObject;
import org.dspace.content.DSpaceObjectLegacySupport;
-import org.dspace.content.WorkspaceItem;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@@ -83,9 +82,6 @@ public class Group extends DSpaceObject implements DSpaceObjectLegacySupport {
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "groups")
private final List parentGroups = new ArrayList<>();
- @ManyToMany(fetch = FetchType.LAZY, mappedBy = "supervisorGroups")
- private final List supervisedItems = new ArrayList<>();
-
@Transient
private boolean groupsChanged;
@@ -219,10 +215,6 @@ public Integer getLegacyId() {
return legacyId;
}
- public List getSupervisedItems() {
- return supervisedItems;
- }
-
/**
* May this Group be renamed or deleted? (The content of any group may be
* changed.)
diff --git a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java
index 389c59f25ab4..9fda372b4f2a 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/GroupServiceImpl.java
@@ -489,9 +489,6 @@ public void delete(Context context, Group group) throws SQLException {
context.addEvent(new Event(Event.DELETE, Constants.GROUP, group.getID(),
group.getName(), getIdentifiers(context, group)));
- //Remove the supervised group from any workspace items linked to us.
- group.getSupervisedItems().clear();
-
// Remove any ResourcePolicies that reference this group
authorizeService.removeGroupPolicies(context, group);
diff --git a/dspace-api/src/main/java/org/dspace/eperson/SubscribeCLITool.java b/dspace-api/src/main/java/org/dspace/eperson/SubscribeCLITool.java
index 42841ea36b9f..dd0bd8287bd3 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/SubscribeCLITool.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/SubscribeCLITool.java
@@ -104,12 +104,12 @@ public static void processDaily(Context context, boolean test) throws SQLExcepti
// Go through the list collating subscriptions for each e-person
for (Subscription subscription : subscriptions) {
- if (!(subscription.getdSpaceObject() != null && subscription.getdSpaceObject() instanceof Collection)) {
+ if (!(subscription.getDSpaceObject() != null && subscription.getDSpaceObject() instanceof Collection)) {
continue;
}
// Does this row relate to the same e-person as the last?
if ((currentEPerson == null)
- || (!subscription.getePerson().getID().equals(currentEPerson
+ || (!subscription.getEPerson().getID().equals(currentEPerson
.getID()))) {
// New e-person. Send mail for previous e-person
if (currentEPerson != null) {
@@ -123,11 +123,11 @@ public static void processDaily(Context context, boolean test) throws SQLExcepti
}
}
- currentEPerson = subscription.getePerson();
+ currentEPerson = subscription.getEPerson();
collections = new ArrayList<>();
}
- collections.add((Collection) subscription.getdSpaceObject());
+ collections.add((Collection) subscription.getDSpaceObject());
}
// Process the last person
diff --git a/dspace-api/src/main/java/org/dspace/eperson/SubscribeServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/SubscribeServiceImpl.java
index ea7317e5e071..2e4d94f4431e 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/SubscribeServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/SubscribeServiceImpl.java
@@ -9,11 +9,15 @@
import java.sql.SQLException;
import java.util.List;
+import java.util.Objects;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
+import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.content.service.CollectionService;
import org.dspace.core.Constants;
@@ -30,33 +34,28 @@
* @version $Revision$
*/
public class SubscribeServiceImpl implements SubscribeService {
- /**
- * log4j logger
- */
- private Logger log = org.apache.logging.log4j.LogManager.getLogger(SubscribeServiceImpl.class);
+
+ private Logger log = LogManager.getLogger(SubscribeServiceImpl.class);
@Autowired(required = true)
- protected SubscriptionDAO subscriptionDAO;
+ private SubscriptionDAO subscriptionDAO;
@Autowired(required = true)
- protected AuthorizeService authorizeService;
+ private AuthorizeService authorizeService;
@Autowired(required = true)
- protected CollectionService collectionService;
-
- protected SubscribeServiceImpl() {
-
- }
+ private CollectionService collectionService;
@Override
- public List findAll(Context context, String resourceType,
- Integer limit, Integer offset) throws Exception {
- if (resourceType == null) {
+ public List findAll(Context context, String resourceType, Integer limit, Integer offset)
+ throws Exception {
+ if (StringUtils.isBlank(resourceType)) {
return subscriptionDAO.findAllOrderedByDSO(context, limit, offset);
} else {
- if (resourceType.equals("Item") || resourceType.equals("Collection") || resourceType.equals("Community")) {
+ if (resourceType.equals(Collection.class.getSimpleName()) ||
+ resourceType.equals(Community.class.getSimpleName())) {
return subscriptionDAO.findAllOrderedByIDAndResourceType(context, resourceType, limit, offset);
} else {
- log.error("Resource type must be Item, Collection or Community");
- throw new Exception("Resource type must be Item, Collection or Community");
+ log.error("Resource type must be Collection or Community");
+ throw new Exception("Resource type must be Collection or Community");
}
}
}
@@ -73,19 +72,18 @@ public Subscription subscribe(Context context, EPerson eperson,
Subscription newSubscription = subscriptionDAO.create(context, new Subscription());
subscriptionParameterList.forEach(subscriptionParameter ->
newSubscription.addParameter(subscriptionParameter));
- newSubscription.setePerson(eperson);
- newSubscription.setdSpaceObject(dSpaceObject);
- newSubscription.setType(type);
+ newSubscription.setEPerson(eperson);
+ newSubscription.setDSpaceObject(dSpaceObject);
+ newSubscription.setSubscriptionType(type);
return newSubscription;
} else {
- throw new AuthorizeException(
- "Only admin or e-person themselves can subscribe");
+ throw new AuthorizeException("Only admin or e-person themselves can subscribe");
}
}
@Override
- public void unsubscribe(Context context, EPerson eperson,
- DSpaceObject dSpaceObject) throws SQLException, AuthorizeException {
+ public void unsubscribe(Context context, EPerson eperson, DSpaceObject dSpaceObject)
+ throws SQLException, AuthorizeException {
// Check authorisation. Must be administrator, or the eperson.
if (authorizeService.isAdmin(context)
|| ((context.getCurrentUser() != null) && (context
@@ -101,45 +99,38 @@ public void unsubscribe(Context context, EPerson eperson,
+ dSpaceObject.getID()));
}
} else {
- throw new AuthorizeException(
- "Only admin or e-person themselves can unsubscribe");
+ throw new AuthorizeException("Only admin or e-person themselves can unsubscribe");
}
}
@Override
- public List getSubscriptionsByEPerson(Context context, EPerson eperson, Integer limit, Integer offset)
+ public List findSubscriptionsByEPerson(Context context, EPerson eperson, Integer limit,Integer offset)
throws SQLException {
return subscriptionDAO.findByEPerson(context, eperson, limit, offset);
}
@Override
- public List getSubscriptionsByEPersonAndDso(Context context,
- EPerson eperson, DSpaceObject dSpaceObject,
- Integer limit, Integer offset)
- throws SQLException {
+ public List findSubscriptionsByEPersonAndDso(Context context, EPerson eperson,
+ DSpaceObject dSpaceObject,
+ Integer limit, Integer offset) throws SQLException {
return subscriptionDAO.findByEPersonAndDso(context, eperson, dSpaceObject, limit, offset);
}
@Override
- public List getAvailableSubscriptions(Context context)
- throws SQLException {
- return getAvailableSubscriptions(context, null);
+ public List findAvailableSubscriptions(Context context) throws SQLException {
+ return findAvailableSubscriptions(context, null);
}
@Override
- public List getAvailableSubscriptions(Context context, EPerson eperson)
- throws SQLException {
- List collections;
- if (eperson != null) {
+ public List findAvailableSubscriptions(Context context, EPerson eperson) throws SQLException {
+ if (Objects.nonNull(eperson)) {
context.setCurrentUser(eperson);
}
- collections = collectionService.findAuthorized(context, null, Constants.ADD);
- return collections;
+ return collectionService.findAuthorized(context, null, Constants.ADD);
}
@Override
- public boolean isSubscribed(Context context, EPerson eperson,
- DSpaceObject dSpaceObject) throws SQLException {
+ public boolean isSubscribed(Context context, EPerson eperson, DSpaceObject dSpaceObject) throws SQLException {
return subscriptionDAO.findByEPersonAndDso(context, eperson, dSpaceObject, -1, -1) != null;
}
@@ -154,94 +145,50 @@ public void deleteByEPerson(Context context, EPerson ePerson) throws SQLExceptio
}
@Override
- public Subscription findById(Context context, int id) throws SQLException, AuthorizeException {
- Subscription subscription = subscriptionDAO.findByID(context, Subscription.class, id);
- if (context.getCurrentUser().equals(subscription.getePerson()) ||
- authorizeService.isAdmin(context, context.getCurrentUser())) {
- return subscription;
- }
- throw new AuthorizeException("Only admin or e-person themselves can edit the subscription");
+ public Subscription findById(Context context, int id) throws SQLException {
+ return subscriptionDAO.findByID(context, Subscription.class, id);
}
@Override
- public Subscription updateSubscription(Context context, Integer id,
- EPerson eperson,
- DSpaceObject dSpaceObject,
- List subscriptionParameterList,
- String type) throws SQLException, AuthorizeException {
- // must be admin or the subscriber of the subscription
- if (authorizeService.isAdmin(context, context.getCurrentUser()) || eperson.equals(context.getCurrentUser())) {
- Subscription subscriptionDB = subscriptionDAO.findByID(context, Subscription.class, id);
- subscriptionDB.removeParameterList();
- subscriptionDB.setType(type);
- subscriptionDB.setdSpaceObject(dSpaceObject);
- subscriptionParameterList.forEach(subscriptionParameter ->
- subscriptionDB.addParameter(subscriptionParameter));
- subscriptionDB.setePerson(eperson);
- subscriptionDAO.save(context, subscriptionDB);
- return subscriptionDB;
- } else {
- throw new AuthorizeException("Only admin or e-person themselves can edit the subscription");
- }
+ public Subscription updateSubscription(Context context, Integer id, String subscriptionType,
+ List subscriptionParameterList)
+ throws SQLException {
+ Subscription subscriptionDB = subscriptionDAO.findByID(context, Subscription.class, id);
+ subscriptionDB.removeParameterList();
+ subscriptionDB.setSubscriptionType(subscriptionType);
+ subscriptionParameterList.forEach(x -> subscriptionDB.addParameter(x));
+ subscriptionDAO.save(context, subscriptionDB);
+ return subscriptionDB;
}
@Override
- public Subscription addSubscriptionParameter(Context context, Integer id,
- SubscriptionParameter subscriptionParameter) throws SQLException, AuthorizeException {
- // must be admin or the subscriber of the subscription
+ public Subscription addSubscriptionParameter(Context context, Integer id, SubscriptionParameter subscriptionParam)
+ throws SQLException {
Subscription subscriptionDB = subscriptionDAO.findByID(context, Subscription.class, id);
- if (authorizeService.isAdmin(context, context.getCurrentUser())
- || subscriptionDB.getePerson().equals(context.getCurrentUser())) {
- subscriptionDB.addParameter(subscriptionParameter);
- subscriptionDAO.save(context, subscriptionDB);
- return subscriptionDB;
- } else {
- throw new AuthorizeException("Only admin or e-person themselves can edit the subscription");
- }
+ subscriptionDB.addParameter(subscriptionParam);
+ subscriptionDAO.save(context, subscriptionDB);
+ return subscriptionDB;
}
@Override
- public Subscription removeSubscriptionParameter(Context context, Integer id,
- SubscriptionParameter subscriptionParameter) throws SQLException, AuthorizeException {
- // must be admin or the subscriber of the subscription
+ public Subscription removeSubscriptionParameter(Context context,Integer id, SubscriptionParameter subscriptionParam)
+ throws SQLException {
Subscription subscriptionDB = subscriptionDAO.findByID(context, Subscription.class, id);
- if (authorizeService.isAdmin(context, context.getCurrentUser())
- || subscriptionDB.getePerson().equals(context.getCurrentUser())) {
- subscriptionDB.removeParameter(subscriptionParameter);
- subscriptionDAO.save(context, subscriptionDB);
- return subscriptionDB;
- } else {
- throw new AuthorizeException("Only admin or e-person themselves can edit the subscription");
- }
+ subscriptionDB.removeParameter(subscriptionParam);
+ subscriptionDAO.save(context, subscriptionDB);
+ return subscriptionDB;
}
@Override
- public void deleteSubscription(Context context, Integer id) throws SQLException, AuthorizeException {
- // initially find the eperson associated with the subscription
- Subscription subscription = subscriptionDAO.findByID(context, Subscription.class, id);
- if (subscription != null) {
- // must be admin or the subscriber of the subscription
- if (authorizeService.isAdmin(context, context.getCurrentUser())
- || subscription.getePerson().equals(context.getCurrentUser())) {
- try {
- subscriptionDAO.delete(context, subscription);
- } catch (SQLException sqlException) {
- throw new SQLException(sqlException);
- }
-
- } else {
- throw new AuthorizeException("Only admin or e-person themselves can delete the subscription");
- }
- } else {
- throw new IllegalArgumentException("Subscription with id " + id + " is not found");
- }
-
+ public void deleteSubscription(Context context, Subscription subscription) throws SQLException {
+ subscriptionDAO.delete(context, subscription);
}
@Override
- public List findAllSubscriptionsByTypeAndFrequency(Context context,
- String type, String frequencyValue) throws SQLException {
- return subscriptionDAO.findAllSubscriptionsByTypeAndFrequency(context, type, frequencyValue);
+ public List findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
+ String subscriptionType, String frequencyValue) throws SQLException {
+ return subscriptionDAO.findAllSubscriptionsBySubscriptionTypeAndFrequency(context, subscriptionType,
+ frequencyValue);
}
@Override
@@ -250,13 +197,14 @@ public Long countAll(Context context) throws SQLException {
}
@Override
- public Long countAllByEPerson(Context context, EPerson ePerson) throws SQLException {
+ public Long countSubscriptionsByEPerson(Context context, EPerson ePerson) throws SQLException {
return subscriptionDAO.countAllByEPerson(context, ePerson);
}
@Override
- public Long countAllByEPersonAndDSO(Context context,
- EPerson ePerson, DSpaceObject dSpaceObject) throws SQLException {
+ public Long countByEPersonAndDSO(Context context, EPerson ePerson, DSpaceObject dSpaceObject)
+ throws SQLException {
return subscriptionDAO.countAllByEPersonAndDso(context, ePerson, dSpaceObject);
}
+
}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/Subscription.java b/dspace-api/src/main/java/org/dspace/eperson/Subscription.java
index 6f38dce058c4..5db63740f477 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/Subscription.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/Subscription.java
@@ -26,8 +26,6 @@
import org.dspace.core.Context;
import org.dspace.core.ReloadableEntity;
-
-
/**
* Database entity representation of the subscription table
*
@@ -43,7 +41,7 @@ public class Subscription implements ReloadableEntity {
@SequenceGenerator(name = "subscription_seq", sequenceName = "subscription_seq", allocationSize = 1)
private Integer id;
- @ManyToOne(fetch = FetchType.LAZY)
+ @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "dspace_object_id")
private DSpaceObject dSpaceObject;
@@ -51,8 +49,13 @@ public class Subscription implements ReloadableEntity {
@JoinColumn(name = "eperson_id")
private EPerson ePerson;
+ /**
+ * Represent subscription type, for example, "content" or "statistics".
+ *
+ * NOTE: Currently, in DSpace we use only one "content"
+ */
@Column(name = "type")
- private String type;
+ private String subscriptionType;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "subscription", cascade = CascadeType.ALL, orphanRemoval = true)
private List subscriptionParameterList = new ArrayList<>();
@@ -61,15 +64,14 @@ public class Subscription implements ReloadableEntity {
* Protected constructor, create object using:
* {@link org.dspace.eperson.service.SubscribeService#subscribe(Context, EPerson, DSpaceObject, List, String)}
*/
- protected Subscription() {
- }
+ protected Subscription() {}
@Override
public Integer getID() {
return id;
}
- public DSpaceObject getdSpaceObject() {
+ public DSpaceObject getDSpaceObject() {
return this.dSpaceObject;
}
@@ -77,24 +79,20 @@ void setDSpaceObject(DSpaceObject dSpaceObject) {
this.dSpaceObject = dSpaceObject;
}
- public EPerson getePerson() {
+ public EPerson getEPerson() {
return ePerson;
}
- public void setePerson(EPerson ePerson) {
+ public void setEPerson(EPerson ePerson) {
this.ePerson = ePerson;
}
- public void setdSpaceObject(DSpaceObject dSpaceObject) {
- this.dSpaceObject = dSpaceObject;
- }
-
- public String getType() {
- return type;
+ public String getSubscriptionType() {
+ return subscriptionType;
}
- public void setType(String type) {
- this.type = type;
+ public void setSubscriptionType(String subscriptionType) {
+ this.subscriptionType = subscriptionType;
}
public List getSubscriptionParameterList() {
@@ -117,4 +115,4 @@ public void removeParameterList() {
public void removeParameter(SubscriptionParameter subscriptionParameter) {
subscriptionParameterList.remove(subscriptionParameter);
}
-}
+}
\ No newline at end of file
diff --git a/dspace-api/src/main/java/org/dspace/eperson/SubscriptionParameter.java b/dspace-api/src/main/java/org/dspace/eperson/SubscriptionParameter.java
index c278f68eb87f..7526535d7fcd 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/SubscriptionParameter.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/SubscriptionParameter.java
@@ -7,7 +7,6 @@
*/
package org.dspace.eperson;
-
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
@@ -18,29 +17,50 @@
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
+import org.dspace.core.ReloadableEntity;
+
/**
* Database entity representation of the subscription_parameter table
+ * SubscriptionParameter represents a frequency with which an user wants to be notified.
*
* @author Alba Aliu at atis.al
*/
-
@Entity
@Table(name = "subscription_parameter")
-public class SubscriptionParameter {
+public class SubscriptionParameter implements ReloadableEntity {
+
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "subscription_parameter_seq")
- @SequenceGenerator(name = "subscription_parameter_seq",
- sequenceName = "subscription_parameter_seq", allocationSize = 1)
+ @SequenceGenerator(name = "subscription_parameter_seq", sequenceName = "subscription_parameter_seq",
+ allocationSize = 1)
@Column(name = "subscription_parameter_id", unique = true)
private Integer id;
+
@ManyToOne
@JoinColumn(name = "subscription_id", nullable = false)
private Subscription subscription;
+
+ /*
+ * Currently, we have only one use case for this attribute: "frequency"
+ */
@Column
private String name;
+
+ /*
+ * Currently, we use this attribute only with following values: "D", "W", "M".
+ * Where D stand for Day, W stand for Week and M stand for Month
+ */
@Column
private String value;
+ public SubscriptionParameter() {}
+
+ public SubscriptionParameter(Integer id, Subscription subscription, String name, String value) {
+ this.id = id;
+ this.subscription = subscription;
+ this.name = name;
+ this.value = value;
+ }
public Subscription getSubscription() {
return subscription;
@@ -66,22 +86,13 @@ public void setValue(String value) {
this.value = value;
}
- public SubscriptionParameter(Integer id, Subscription subscription, String name, String value) {
- this.id = id;
- this.subscription = subscription;
- this.name = name;
- this.value = value;
- }
-
- public SubscriptionParameter() {
- }
-
- public Integer getId() {
+ @Override
+ public Integer getID() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
-}
+}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/SupervisorServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/SupervisorServiceImpl.java
deleted file mode 100644
index 64180a5e2231..000000000000
--- a/dspace-api/src/main/java/org/dspace/eperson/SupervisorServiceImpl.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * The contents of this file are subject to the license and copyright
- * detailed in the LICENSE and NOTICE files at the root of the source
- * tree and available online at
- *
- * http://www.dspace.org/license/
- */
-package org.dspace.eperson;
-
-import java.sql.SQLException;
-
-import org.dspace.authorize.AuthorizeException;
-import org.dspace.authorize.ResourcePolicy;
-import org.dspace.authorize.service.ResourcePolicyService;
-import org.dspace.content.Item;
-import org.dspace.content.WorkspaceItem;
-import org.dspace.content.service.ItemService;
-import org.dspace.core.Constants;
-import org.dspace.core.Context;
-import org.dspace.eperson.service.SupervisorService;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public class SupervisorServiceImpl implements SupervisorService {
-
- @Autowired(required = true)
- protected ItemService itemService;
- @Autowired(required = true)
- protected ResourcePolicyService resourcePolicyService;
-
- protected SupervisorServiceImpl() {
- }
-
- @Override
- public boolean isOrder(Context context, WorkspaceItem workspaceItem, Group group)
- throws SQLException {
- return workspaceItem.getSupervisorGroups().contains(group);
- }
-
- @Override
- public void remove(Context context, WorkspaceItem workspaceItem, Group group)
- throws SQLException, AuthorizeException {
- // get the workspace item and the group from the request values
- workspaceItem.getSupervisorGroups().remove(group);
-
- // get the item and have it remove the policies for the group
- Item item = workspaceItem.getItem();
- itemService.removeGroupPolicies(context, item, group);
- }
-
- @Override
- public void add(Context context, Group group, WorkspaceItem workspaceItem, int policy)
- throws SQLException, AuthorizeException {
- // make a table row in the database table, and update with the relevant
- // details
- workspaceItem.getSupervisorGroups().add(group);
- group.getSupervisedItems().add(workspaceItem);
-
- // If a default policy type has been requested, apply the policies using
- // the DSpace API for doing so
- if (policy != POLICY_NONE) {
- Item item = workspaceItem.getItem();
-
- // "Editor" implies READ, WRITE, ADD permissions
- // "Observer" implies READ permissions
- if (policy == POLICY_EDITOR) {
- ResourcePolicy r = resourcePolicyService.create(context);
- r.setdSpaceObject(item);
- r.setGroup(group);
- r.setAction(Constants.READ);
- resourcePolicyService.update(context, r);
-
- r = resourcePolicyService.create(context);
- r.setdSpaceObject(item);
- r.setGroup(group);
- r.setAction(Constants.WRITE);
- resourcePolicyService.update(context, r);
-
- r = resourcePolicyService.create(context);
- r.setdSpaceObject(item);
- r.setGroup(group);
- r.setAction(Constants.ADD);
- resourcePolicyService.update(context, r);
-
- } else if (policy == POLICY_OBSERVER) {
- ResourcePolicy r = resourcePolicyService.create(context);
- r.setdSpaceObject(item);
- r.setGroup(group);
- r.setAction(Constants.READ);
- resourcePolicyService.update(context, r);
- }
- }
- }
-}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/SubscriptionDAO.java b/dspace-api/src/main/java/org/dspace/eperson/dao/SubscriptionDAO.java
index a22ff4596f30..4d762c1775dd 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/dao/SubscriptionDAO.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/dao/SubscriptionDAO.java
@@ -26,32 +26,125 @@
*/
public interface SubscriptionDAO extends GenericDAO {
+ /**
+ * Delete all subscription of provided dSpaceObject
+ *
+ * @param context DSpace context object
+ * @param dSpaceObject DSpace resource
+ * @throws SQLException If database error
+ */
public void deleteByDspaceObject(Context context, DSpaceObject dSpaceObject) throws SQLException;
- public List findByEPerson(Context context,
- EPerson eperson, Integer limit, Integer offset) throws SQLException;
+ /**
+ * Return a paginated list of all subscriptions of the eperson
+ *
+ * @param context DSpace context object
+ * @param eperson ePerson whose subscriptions want to find
+ * @param limit Paging limit
+ * @param offset The position of the first result to return
+ * @return
+ * @throws SQLException If database error
+ */
+ public List findByEPerson(Context context, EPerson eperson, Integer limit, Integer offset)
+ throws SQLException;
- public List findByEPersonAndDso(Context context,
- EPerson eperson, DSpaceObject dSpaceObject,
+ /**
+ * Return a paginated list of subscriptions related to a DSpaceObject belong to an ePerson
+ *
+ * @param context DSpace context object
+ * @param eperson ePerson whose subscriptions want to find
+ * @param dSpaceObject DSpaceObject of whom subscriptions want to find
+ * @param limit Paging limit
+ * @param offset The position of the first result to return
+ * @return
+ * @throws SQLException If database error
+ */
+ public List findByEPersonAndDso(Context context, EPerson eperson, DSpaceObject dSpaceObject,
Integer limit, Integer offset) throws SQLException;
+ /**
+ * Delete all subscription of provided ePerson
+ *
+ * @param context DSpace context object
+ * @param eperson ePerson whose subscriptions want to delete
+ * @throws SQLException If database error
+ */
public void deleteByEPerson(Context context, EPerson eperson) throws SQLException;
- public void deleteByDSOAndEPerson(Context context, DSpaceObject dSpaceObject, EPerson eperson)
- throws SQLException;
+ /**
+ * Delete all subscriptions related to a DSpaceObject belong to an ePerson
+ *
+ * @param context DSpace context object
+ * @param dSpaceObject DSpaceObject of whom subscriptions want to delete
+ * @param eperson ePerson whose subscriptions want to delete
+ * @throws SQLException If database error
+ */
+ public void deleteByDSOAndEPerson(Context context, DSpaceObject dSpaceObject, EPerson eperson) throws SQLException;
+ /**
+ * Return a paginated list of all subscriptions ordered by ID and resourceType
+ *
+ * @param context DSpace context object
+ * @param resourceType Could be Collection or Community
+ * @param limit Paging limit
+ * @param offset The position of the first result to return
+ * @return
+ * @throws SQLException If database error
+ */
public List findAllOrderedByIDAndResourceType(Context context, String resourceType,
Integer limit, Integer offset) throws SQLException;
+ /**
+ * Return a paginated list of subscriptions ordered by DSpaceObject
+ *
+ * @param context DSpace context object
+ * @param limit Paging limit
+ * @param offset The position of the first result to return
+ * @return
+ * @throws SQLException If database error
+ */
public List findAllOrderedByDSO(Context context, Integer limit, Integer offset) throws SQLException;
- public List findAllSubscriptionsByTypeAndFrequency(Context context,
- String type, String frequencyValue) throws SQLException;
+ /**
+ * Return a list of all subscriptions by subscriptionType and frequency
+ *
+ * @param context DSpace context object
+ * @param subscriptionType Could be "content" or "statistics". NOTE: in DSpace we have only "content"
+ * @param frequencyValue Could be "D" stand for Day, "W" stand for Week, and "M" stand for Month
+ * @return
+ * @throws SQLException If database error
+ */
+ public List findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
+ String subscriptionType, String frequencyValue) throws SQLException;
+ /**
+ * Count all subscriptions
+ *
+ * @param context DSpace context object
+ * @return Total of all subscriptions
+ * @throws SQLException If database error
+ */
public Long countAll(Context context) throws SQLException;
+ /**
+ * Count all subscriptions belong to an ePerson
+ *
+ * @param context DSpace context object
+ * @param ePerson ePerson whose subscriptions want count
+ * @return Total of all subscriptions belong to an ePerson
+ * @throws SQLException If database error
+ */
public Long countAllByEPerson(Context context, EPerson ePerson) throws SQLException;
- public Long countAllByEPersonAndDso(Context context, EPerson ePerson,
- DSpaceObject dSpaceObject) throws SQLException;
+ /**
+ * Count all subscriptions related to a DSpaceObject belong to an ePerson
+ *
+ * @param context DSpace context object
+ * @param ePerson ePerson whose subscriptions want count
+ * @param dSpaceObject DSpaceObject of whom subscriptions want count
+ * @return
+ * @throws SQLException If database error
+ */
+ public Long countAllByEPersonAndDso(Context context, EPerson ePerson,DSpaceObject dSpaceObject) throws SQLException;
+
}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/SubscriptionParameterDAO.java b/dspace-api/src/main/java/org/dspace/eperson/dao/SubscriptionParameterDAO.java
index f41be1e50b11..ea9c7b0bbd37 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/dao/SubscriptionParameterDAO.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/dao/SubscriptionParameterDAO.java
@@ -19,5 +19,4 @@
* @author Alba Aliu at atis.al
*/
public interface SubscriptionParameterDAO extends GenericDAO {
-
}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionDAOImpl.java
index cffb0bb1ea6d..6c36211f310c 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionDAOImpl.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionDAOImpl.java
@@ -35,13 +35,14 @@
* @author kevinvandevelde at atmire.com
*/
public class SubscriptionDAOImpl extends AbstractHibernateDAO implements SubscriptionDAO {
+
protected SubscriptionDAOImpl() {
super();
}
@Override
- public List findByEPerson(Context context, EPerson eperson,
- Integer limit, Integer offset) throws SQLException {
+ public List findByEPerson(Context context, EPerson eperson, Integer limit, Integer offset)
+ throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
javax.persistence.criteria.CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class);
Root subscriptionRoot = criteriaQuery.from(Subscription.class);
@@ -51,7 +52,6 @@ public List findByEPerson(Context context, EPerson eperson,
orderList.add(criteriaBuilder.asc(subscriptionRoot.get(Subscription_.dSpaceObject)));
criteriaQuery.orderBy(orderList);
return list(context, criteriaQuery, false, Subscription.class, limit, offset);
-
}
@Override
@@ -64,7 +64,7 @@ public List findByEPersonAndDso(Context context, EPerson eperson,
Root subscriptionRoot = criteriaQuery.from(Subscription.class);
criteriaQuery.select(subscriptionRoot);
criteriaQuery.where(criteriaBuilder.and(criteriaBuilder.equal(
- subscriptionRoot.get(Subscription_.ePerson), eperson),
+ subscriptionRoot.get(Subscription_.ePerson), eperson),
criteriaBuilder.equal(subscriptionRoot.get(Subscription_.dSpaceObject), dSpaceObject)
));
List orderList = new LinkedList<>();
@@ -132,14 +132,16 @@ public List findAllOrderedByDSO(Context context, Integer limit, In
}
@Override
- public List findAllSubscriptionsByTypeAndFrequency(Context context,
- String type, String frequencyValue) throws SQLException {
+ public List findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
+ String subscriptionType, String frequencyValue) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Subscription.class);
Root subscriptionRoot = criteriaQuery.from(Subscription.class);
criteriaQuery.select(subscriptionRoot);
Join childJoin = subscriptionRoot.join("subscriptionParameterList");
- criteriaQuery.where(criteriaBuilder.and(criteriaBuilder.equal(subscriptionRoot.get(Subscription_.TYPE), type),
+ criteriaQuery.where(
+ criteriaBuilder.and(
+ criteriaBuilder.equal(subscriptionRoot.get(Subscription_.SUBSCRIPTION_TYPE), subscriptionType),
criteriaBuilder.equal(childJoin.get(SubscriptionParameter_.name), "frequency"),
criteriaBuilder.equal(childJoin.get(SubscriptionParameter_.value), frequencyValue)
));
@@ -182,4 +184,5 @@ public Long countAllByEPersonAndDso(Context context,
Query query = this.getHibernateSession(context).createQuery(cq);
return (Long) query.getSingleResult();
}
-}
+
+}
\ No newline at end of file
diff --git a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionParameterDAOImpl.java b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionParameterDAOImpl.java
index eee80a73a510..37af787ed3a5 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionParameterDAOImpl.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/dao/impl/SubscriptionParameterDAOImpl.java
@@ -18,9 +18,11 @@
*
* @author Alba Aliu at atis.al
*/
-public class SubscriptionParameterDAOImpl extends AbstractHibernateDAO
- implements SubscriptionParameterDAO {
+public class SubscriptionParameterDAOImpl extends AbstractHibernateDAO
+ implements SubscriptionParameterDAO {
+
protected SubscriptionParameterDAOImpl() {
super();
}
+
}
\ No newline at end of file
diff --git a/dspace-api/src/main/java/org/dspace/eperson/factory/EPersonServiceFactory.java b/dspace-api/src/main/java/org/dspace/eperson/factory/EPersonServiceFactory.java
index f7ce13a8a397..b80c37f13ff5 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/factory/EPersonServiceFactory.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/factory/EPersonServiceFactory.java
@@ -12,7 +12,6 @@
import org.dspace.eperson.service.GroupService;
import org.dspace.eperson.service.RegistrationDataService;
import org.dspace.eperson.service.SubscribeService;
-import org.dspace.eperson.service.SupervisorService;
import org.dspace.services.factory.DSpaceServicesFactory;
/**
@@ -33,8 +32,6 @@ public abstract class EPersonServiceFactory {
public abstract SubscribeService getSubscribeService();
- public abstract SupervisorService getSupervisorService();
-
public static EPersonServiceFactory getInstance() {
return DSpaceServicesFactory.getInstance().getServiceManager()
.getServiceByName("ePersonServiceFactory", EPersonServiceFactory.class);
diff --git a/dspace-api/src/main/java/org/dspace/eperson/factory/EPersonServiceFactoryImpl.java b/dspace-api/src/main/java/org/dspace/eperson/factory/EPersonServiceFactoryImpl.java
index 33d9249b6bfd..c4a6cbe9964c 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/factory/EPersonServiceFactoryImpl.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/factory/EPersonServiceFactoryImpl.java
@@ -12,7 +12,6 @@
import org.dspace.eperson.service.GroupService;
import org.dspace.eperson.service.RegistrationDataService;
import org.dspace.eperson.service.SubscribeService;
-import org.dspace.eperson.service.SupervisorService;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -33,8 +32,6 @@ public class EPersonServiceFactoryImpl extends EPersonServiceFactory {
private AccountService accountService;
@Autowired(required = true)
private SubscribeService subscribeService;
- @Autowired(required = true)
- private SupervisorService supervisorService;
@Override
public EPersonService getEPersonService() {
@@ -61,8 +58,4 @@ public SubscribeService getSubscribeService() {
return subscribeService;
}
- @Override
- public SupervisorService getSupervisorService() {
- return supervisorService;
- }
}
diff --git a/dspace-api/src/main/java/org/dspace/eperson/service/SubscribeService.java b/dspace-api/src/main/java/org/dspace/eperson/service/SubscribeService.java
index 466789294b0a..e70f40e0edf0 100644
--- a/dspace-api/src/main/java/org/dspace/eperson/service/SubscribeService.java
+++ b/dspace-api/src/main/java/org/dspace/eperson/service/SubscribeService.java
@@ -38,22 +38,26 @@ public interface SubscribeService {
* @return list of Subscription objects
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public List findAll(Context context, String resourceType,
- Integer limit, Integer offset) throws Exception;
+ public List findAll(Context context, String resourceType, Integer limit, Integer offset)
+ throws Exception;
/**
- * Subscribe an e-person to a collection. An e-mail will be sent every day a
- * new item appears in the collection.
- *
- * @param context DSpace context
- * @throws SQLException An exception that provides information on a database access error or other errors.
- * @throws AuthorizeException Exception indicating the current user of the context does not have permission
- * to perform a particular action.
+ * Subscribe an EPerson to a dSpaceObject (Collection or Community). An e-mail will be sent every day a
+ * new item appears in the Collection or Community.
+ *
+ * @param context DSpace context object
+ * @param eperson EPerson to subscribe
+ * @param dSpaceObject DSpaceObject to subscribe
+ * @param subscriptionParameters list of @SubscriptionParameter
+ * @param subscriptionType Currently supported only "content"
+ * @return
+ * @throws SQLException An exception that provides information on a database access error or other errors.
+ * @throws AuthorizeException Exception indicating the current user of the context does not have permission
+ * to perform a particular action.
*/
- public Subscription subscribe(Context context, EPerson eperson,
- DSpaceObject dSpaceObject,
- List subscriptionParameterList,
- String type) throws SQLException, AuthorizeException;
+ public Subscription subscribe(Context context, EPerson eperson, DSpaceObject dSpaceObject,
+ List subscriptionParameters,
+ String subscriptionType) throws SQLException, AuthorizeException;
/**
* Unsubscribe an e-person to a collection. Passing in null
@@ -67,8 +71,8 @@ public Subscription subscribe(Context context, EPerson eperson,
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
* to perform a particular action.
*/
- public void unsubscribe(Context context, EPerson eperson,
- DSpaceObject dSpaceObject) throws SQLException, AuthorizeException;
+ public void unsubscribe(Context context, EPerson eperson, DSpaceObject dSpaceObject)
+ throws SQLException, AuthorizeException;
/**
* Find out which collections an e-person is subscribed to
@@ -80,8 +84,8 @@ public void unsubscribe(Context context, EPerson eperson,
* @return array of collections e-person is subscribed to
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public List getSubscriptionsByEPerson(Context context, EPerson eperson,
- Integer limit, Integer offset) throws SQLException;
+ public List findSubscriptionsByEPerson(Context context, EPerson eperson, Integer limit,Integer offset)
+ throws SQLException;
/**
* Find out which collections an e-person is subscribed to and related with dso
@@ -94,11 +98,9 @@ public List getSubscriptionsByEPerson(Context context, EPerson epe
* @return array of collections e-person is subscribed to and related with dso
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public List getSubscriptionsByEPersonAndDso(Context context,
- EPerson eperson,
+ public List findSubscriptionsByEPersonAndDso(Context context, EPerson eperson,
DSpaceObject dSpaceObject,
- Integer limit,
- Integer offset) throws SQLException;
+ Integer limit, Integer offset) throws SQLException;
/**
* Find out which collections the currently logged in e-person can subscribe to
@@ -107,8 +109,7 @@ public List getSubscriptionsByEPersonAndDso(Context context,
* @return array of collections the currently logged in e-person can subscribe to
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public List getAvailableSubscriptions(Context context)
- throws SQLException;
+ public List findAvailableSubscriptions(Context context) throws SQLException;
/**
* Find out which collections an e-person can subscribe to
@@ -118,8 +119,7 @@ public List getAvailableSubscriptions(Context context)
* @return array of collections e-person can subscribe to
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public List getAvailableSubscriptions(Context context, EPerson eperson)
- throws SQLException;
+ public List findAvailableSubscriptions(Context context, EPerson eperson) throws SQLException;
/**
* Is that e-person subscribed to that collection?
@@ -130,8 +130,7 @@ public List getAvailableSubscriptions(Context context, EPerson epers
* @return true
if they are subscribed
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public boolean isSubscribed(Context context, EPerson eperson,
- DSpaceObject dSpaceObject) throws SQLException;
+ public boolean isSubscribed(Context context, EPerson eperson, DSpaceObject dSpaceObject) throws SQLException;
/**
* Delete subscription by collection.
@@ -158,23 +157,19 @@ public boolean isSubscribed(Context context, EPerson eperson,
* @param id the id of subscription to be searched
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public Subscription findById(Context context, int id) throws SQLException, AuthorizeException;
+ public Subscription findById(Context context, int id) throws SQLException;
/**
* Updates a subscription by id
*
* @param context DSpace context
* @param id Integer id
- * @param eperson EPerson eperson
- * @param dSpaceObject DSpaceObject dSpaceObject
* @param subscriptionParameterList List subscriptionParameterList
- * @param type String type
+ * @param subscriptionType type
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public Subscription updateSubscription(Context context, Integer id, EPerson eperson,
- DSpaceObject dSpaceObject,
- List subscriptionParameterList,
- String type) throws SQLException, AuthorizeException;
+ public Subscription updateSubscription(Context context, Integer id, String subscriptionType,
+ List subscriptionParameterList) throws SQLException;
/**
* Adds a parameter to a subscription
@@ -184,48 +179,46 @@ public Subscription updateSubscription(Context context, Integer id, EPerson eper
* @param subscriptionParameter SubscriptionParameter subscriptionParameter
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public Subscription addSubscriptionParameter(Context context, Integer id,
- SubscriptionParameter subscriptionParameter)
- throws SQLException, AuthorizeException;
+ public Subscription addSubscriptionParameter(Context context,Integer id,
+ SubscriptionParameter subscriptionParameter) throws SQLException;
/**
* Deletes a parameter from subscription
*
* @param context DSpace context
* @param id Integer id
- * @param subscriptionParameter SubscriptionParameter subscriptionParameter
- * @throws SQLException An exception that provides information on a database access error or other errors.
+ * @param subscriptionParam SubscriptionParameter subscriptionParameter
+ * @throws SQLException An exception that provides information on a database access error or other errors.
*/
public Subscription removeSubscriptionParameter(Context context, Integer id,
- SubscriptionParameter subscriptionParameter) throws SQLException, AuthorizeException;
+ SubscriptionParameter subscriptionParam) throws SQLException;
/**
* Deletes a subscription
*
* @param context DSpace context
- * @param id Integer id of subscription
+ * @param subscription The subscription to delete
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public void deleteSubscription(Context context, Integer id) throws SQLException, AuthorizeException;
+ public void deleteSubscription(Context context, Subscription subscription) throws SQLException;
/**
- * Finds all subscriptions having given type and frequency
+ * Finds all subscriptions by subscriptionType and frequency
*
- * @param context DSpace context
- * @param type String type of subscription
- * @param frequencyValue String frequency value of subscription
- * @throws SQLException An exception that provides information on a database access error or other errors.
+ * @param context DSpace context
+ * @param subscriptionType Could be "content" or "statistics". NOTE: in DSpace we have only "content"
+ * @param frequencyValue Could be "D" stand for Day, "W" stand for Week, and "M" stand for Month
+ * @throws SQLException An exception that provides information on a database access error or other errors.
*/
- public List findAllSubscriptionsByTypeAndFrequency(Context context,
- String type, String frequencyValue) throws SQLException;
-
+ public List findAllSubscriptionsBySubscriptionTypeAndFrequency(Context context,
+ String subscriptionType, String frequencyValue) throws SQLException;
/**
* Counts all subscriptions
*
* @param context DSpace context
*/
- public Long countAll(Context context) throws SQLException, AuthorizeException;
+ public Long countAll(Context context) throws SQLException;
/**
* Counts all subscriptions by ePerson
@@ -233,8 +226,7 @@ public List findAllSubscriptionsByTypeAndFrequency(Context context
* @param context DSpace context
* @param ePerson EPerson ePerson
*/
- public Long countAllByEPerson(Context context, EPerson ePerson) throws SQLException, AuthorizeException;
-
+ public Long countSubscriptionsByEPerson(Context context, EPerson ePerson) throws SQLException;
/**
* Counts all subscriptions by ePerson and DSO
@@ -243,6 +235,6 @@ public List findAllSubscriptionsByTypeAndFrequency(Context context
* @param ePerson EPerson ePerson
* @param dSpaceObject DSpaceObject dSpaceObject
*/
- public Long countAllByEPersonAndDSO(Context context, EPerson ePerson,
- DSpaceObject dSpaceObject) throws SQLException, AuthorizeException;
-}
+ public Long countByEPersonAndDSO(Context context, EPerson ePerson, DSpaceObject dSpaceObject) throws SQLException;
+
+}
\ No newline at end of file
diff --git a/dspace-api/src/main/java/org/dspace/eperson/service/SupervisorService.java b/dspace-api/src/main/java/org/dspace/eperson/service/SupervisorService.java
deleted file mode 100644
index 470c9133e59a..000000000000
--- a/dspace-api/src/main/java/org/dspace/eperson/service/SupervisorService.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * The contents of this file are subject to the license and copyright
- * detailed in the LICENSE and NOTICE files at the root of the source
- * tree and available online at
- *
- * http://www.dspace.org/license/
- */
-package org.dspace.eperson.service;
-
-import java.sql.SQLException;
-
-import org.dspace.authorize.AuthorizeException;
-import org.dspace.content.WorkspaceItem;
-import org.dspace.core.Context;
-import org.dspace.eperson.Group;
-
-/**
- * Class to represent the supervisor, primarily for use in applying supervisor
- * activities to the database, such as setting and unsetting supervision
- * orders and so forth.
- *
- * @author Richard Jones
- * @version $Revision$
- */
-public interface SupervisorService {
-
- /**
- * value to use for no policy set
- */
- public static final int POLICY_NONE = 0;
-
- /**
- * value to use for editor policies
- */
- public static final int POLICY_EDITOR = 1;
-
- /**
- * value to use for observer policies
- */
- public static final int POLICY_OBSERVER = 2;
-
- /**
- * finds out if there is a supervision order that matches this set
- * of values
- *
- * @param context the context this object exists in
- * @param workspaceItem the workspace item to be supervised
- * @param group the group to be doing the supervising
- * @return boolean true if there is an order that matches, false if not
- * @throws SQLException An exception that provides information on a database access error or other errors.
- */
- public boolean isOrder(Context context, WorkspaceItem workspaceItem, Group group)
- throws SQLException;
-
- /**
- * removes the requested group from the requested workspace item in terms
- * of supervision. This also removes all the policies that group has
- * associated with the item
- *
- * @param context the context this object exists in
- * @param workspaceItem the ID of the workspace item
- * @param group the ID of the group to be removed from the item
- * @throws SQLException An exception that provides information on a database access error or other errors.
- * @throws AuthorizeException Exception indicating the current user of the context does not have permission
- * to perform a particular action.
- */
- public void remove(Context context, WorkspaceItem workspaceItem, Group group)
- throws SQLException, AuthorizeException;
-
- /**
- * adds a supervision order to the database
- *
- * @param context the context this object exists in
- * @param group the ID of the group which will supervise
- * @param workspaceItem the ID of the workspace item to be supervised
- * @param policy String containing the policy type to be used
- * @throws SQLException An exception that provides information on a database access error or other errors.
- * @throws AuthorizeException Exception indicating the current user of the context does not have permission
- * to perform a particular action.
- */
- public void add(Context context, Group group, WorkspaceItem workspaceItem, int policy)
- throws SQLException, AuthorizeException;
-}
diff --git a/dspace-api/src/main/java/org/dspace/external/OpenAIRERestConnector.java b/dspace-api/src/main/java/org/dspace/external/OpenAIRERestConnector.java
index 5e45d6324d2c..b0aa4aba13a9 100644
--- a/dspace-api/src/main/java/org/dspace/external/OpenAIRERestConnector.java
+++ b/dspace-api/src/main/java/org/dspace/external/OpenAIRERestConnector.java
@@ -335,7 +335,7 @@ public void setClientSecret(String clientSecret) {
/**
* tokenUsage true to enable the usage of an access token
*
- * @param tokenUsage
+ * @param tokenEnabled true/false
*/
@Autowired(required = false)
public void setTokenEnabled(boolean tokenEnabled) {
diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/LiveImportDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/LiveImportDataProvider.java
index 8a1475f05af9..21c14813f93d 100644
--- a/dspace-api/src/main/java/org/dspace/external/provider/impl/LiveImportDataProvider.java
+++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/LiveImportDataProvider.java
@@ -47,6 +47,14 @@ public String getSourceIdentifier() {
return sourceIdentifier;
}
+ public QuerySource getQuerySource() {
+ return querySource;
+ }
+
+ public void setQuerySource(QuerySource querySource) {
+ this.querySource = querySource;
+ }
+
/**
* This method set the SourceIdentifier for the ExternalDataProvider
* @param sourceIdentifier The UNIQUE sourceIdentifier to be set on any LiveImport data provider
@@ -57,8 +65,7 @@ public void setSourceIdentifier(String sourceIdentifier) {
/**
* This method set the MetadataSource for the ExternalDataProvider
- * @param querySource {@link org.dspace.importer.external.service.components.MetadataSource}
- * implementation used to process the input data
+ * @param querySource Source {@link org.dspace.importer.external.service.components.QuerySource} implementation used to process the input data
*/
public void setMetadataSource(QuerySource querySource) {
this.querySource = querySource;
@@ -83,9 +90,8 @@ public void setDisplayMetadata(String displayMetadata) {
@Override
public Optional getExternalDataObject(String id) {
try {
- ImportRecord record = querySource.getRecord(id);
- ExternalDataObject externalDataObject = getExternalDataObject(record);
- return Optional.ofNullable(externalDataObject);
+ ExternalDataObject externalDataObject = getExternalDataObject(querySource.getRecord(id));
+ return Optional.of(externalDataObject);
} catch (MetadataSourceException e) {
throw new RuntimeException(
"The live import provider " + querySource.getImportSource() + " throws an exception", e);
@@ -129,8 +135,9 @@ public int getNumberOfResults(String query) {
* @return
*/
private ExternalDataObject getExternalDataObject(ImportRecord record) {
- if (record == null || getFirstValue(record, recordIdMetadata) == null) {
- return null;
+ //return 400 if no record were found
+ if (record == null) {
+ throw new IllegalArgumentException("No record found for query or id");
}
ExternalDataObject externalDataObject = new ExternalDataObject(sourceIdentifier);
String id = getFirstValue(record, recordIdMetadata);
@@ -160,7 +167,4 @@ private String getFirstValue(ImportRecord record, String metadata) {
return id;
}
- public QuerySource getQuerySource() {
- return querySource;
- }
}
diff --git a/dspace-api/src/main/java/org/dspace/handle/HandleServiceImpl.java b/dspace-api/src/main/java/org/dspace/handle/HandleServiceImpl.java
index 4aff1e2b5bc8..6d386395ab33 100644
--- a/dspace-api/src/main/java/org/dspace/handle/HandleServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/handle/HandleServiceImpl.java
@@ -9,6 +9,7 @@
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -211,17 +212,17 @@ public String createHandle(Context context, DSpaceObject dso,
@Override
public void unbindHandle(Context context, DSpaceObject dso)
throws SQLException {
- List handles = getInternalHandles(context, dso);
- if (CollectionUtils.isNotEmpty(handles)) {
- for (Handle handle : handles) {
+ Iterator handles = dso.getHandles().iterator();
+ if (handles.hasNext()) {
+ while (handles.hasNext()) {
+ final Handle handle = handles.next();
+ handles.remove();
//Only set the "resouce_id" column to null when unbinding a handle.
// We want to keep around the "resource_type_id" value, so that we
// can verify during a restore whether the same *type* of resource
// is reusing this handle!
handle.setDSpaceObject(null);
- //Also remove the handle from the DSO list to keep a consistent model
- dso.getHandles().remove(handle);
handleDAO.save(context, handle);
@@ -256,7 +257,7 @@ public DSpaceObject resolveToObject(Context context, String handle)
@Override
public String findHandle(Context context, DSpaceObject dso)
throws SQLException {
- List handles = getInternalHandles(context, dso);
+ List handles = dso.getHandles();
if (CollectionUtils.isEmpty(handles)) {
return null;
} else {
@@ -328,20 +329,6 @@ public void modifyHandleDSpaceObject(Context context, String handle, DSpaceObjec
////////////////////////////////////////
// Internal methods
////////////////////////////////////////
-
- /**
- * Return the handle for an Object, or null if the Object has no handle.
- *
- * @param context DSpace context
- * @param dso DSpaceObject for which we require our handles
- * @return The handle for object, or null if the object has no handle.
- * @throws SQLException If a database error occurs
- */
- protected List getInternalHandles(Context context, DSpaceObject dso)
- throws SQLException {
- return handleDAO.getHandlesByDSpaceObject(context, dso);
- }
-
/**
* Find the database row corresponding to handle.
*
diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java
index 66e7b94a4bd4..b70eda960d35 100644
--- a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java
+++ b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java
@@ -21,6 +21,7 @@
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.logic.Filter;
import org.dspace.content.logic.LogicalStatementException;
+import org.dspace.content.logic.TrueFilter;
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
@@ -28,6 +29,7 @@
import org.dspace.identifier.doi.DOIIdentifierException;
import org.dspace.identifier.doi.DOIIdentifierNotApplicableException;
import org.dspace.identifier.service.DOIService;
+import org.dspace.services.factory.DSpaceServicesFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -44,6 +46,7 @@
* Any identifier a method of this class returns is a string in the following format: doi:10.123/456.
*
* @author Pascal-Nicolas Becker
+ * @author Kim Shepherd
*/
public class DOIIdentifierProvider extends FilteredIdentifierProvider {
private static final Logger log = LoggerFactory.getLogger(DOIIdentifierProvider.class);
@@ -71,16 +74,44 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
public static final String MD_SCHEMA = "dc";
public static final String DOI_ELEMENT = "identifier";
public static final String DOI_QUALIFIER = "uri";
-
+ // The DOI is queued for registered with the service provider
public static final Integer TO_BE_REGISTERED = 1;
+ // The DOI is queued for reservation with the service provider
public static final Integer TO_BE_RESERVED = 2;
+ // The DOI has been registered online
public static final Integer IS_REGISTERED = 3;
+ // The DOI has been reserved online
public static final Integer IS_RESERVED = 4;
+ // The DOI is reserved and requires an updated metadata record to be sent to the service provider
public static final Integer UPDATE_RESERVED = 5;
+ // The DOI is registered and requires an updated metadata record to be sent to the service provider
public static final Integer UPDATE_REGISTERED = 6;
+ // The DOI metadata record should be updated before performing online registration
public static final Integer UPDATE_BEFORE_REGISTRATION = 7;
+ // The DOI will be deleted locally and marked as deleted in the DOI service provider
public static final Integer TO_BE_DELETED = 8;
+ // The DOI has been deleted and is no longer associated with an item
public static final Integer DELETED = 9;
+ // The DOI is created in the database and is waiting for either successful filter check on item install or
+ // manual intervention by an administrator to proceed to reservation or registration
+ public static final Integer PENDING = 10;
+ // The DOI is created in the database, but no more context is known
+ public static final Integer MINTED = 11;
+
+ public static final String[] statusText = {
+ "UNKNOWN", // 0
+ "TO_BE_REGISTERED", // 1
+ "TO_BE_RESERVED", // 2
+ "IS_REGISTERED", // 3
+ "IS_RESERVED", // 4
+ "UPDATE_RESERVED", // 5
+ "UPDATE_REGISTERED", // 6
+ "UPDATE_BEFORE_REGISTRATION", // 7
+ "TO_BE_DELETED", // 8
+ "DELETED", // 9
+ "PENDING", // 10
+ "MINTED", // 11
+ };
@Autowired(required = true)
protected DOIService doiService;
@@ -89,8 +120,6 @@ public class DOIIdentifierProvider extends FilteredIdentifierProvider {
@Autowired(required = true)
protected ItemService itemService;
- protected Filter filterService;
-
/**
* Empty / default constructor for Spring
*/
@@ -153,16 +182,6 @@ public void setDOIConnector(DOIConnector connector) {
this.connector = connector;
}
- /**
- * Set the Filter to use when testing items to see if a DOI should be registered
- * Spring will use this setter to set the filter from the configured property in identifier-services.xml
- * @param filterService - an object implementing the org.dspace.content.logic.Filter interface
- */
- @Override
- public void setFilterService(Filter filterService) {
- this.filterService = filterService;
- }
-
/**
* This identifier provider supports identifiers of type
* {@link org.dspace.identifier.DOI}.
@@ -206,7 +225,7 @@ public boolean supports(String identifier) {
@Override
public String register(Context context, DSpaceObject dso)
throws IdentifierException {
- return register(context, dso, false);
+ return register(context, dso, this.filter);
}
/**
@@ -219,29 +238,29 @@ public String register(Context context, DSpaceObject dso)
@Override
public void register(Context context, DSpaceObject dso, String identifier)
throws IdentifierException {
- register(context, dso, identifier, false);
+ register(context, dso, identifier, this.filter);
}
/**
* Register a new DOI for a given DSpaceObject
* @param context - DSpace context
* @param dso - DSpaceObject identified by the new DOI
- * @param skipFilter - boolean indicating whether to skip any filtering of items before performing registration
+ * @param filter - Logical item filter to determine whether this identifier should be registered
* @throws IdentifierException
*/
@Override
- public String register(Context context, DSpaceObject dso, boolean skipFilter)
+ public String register(Context context, DSpaceObject dso, Filter filter)
throws IdentifierException {
if (!(dso instanceof Item)) {
// DOI are currently assigned only to Item
return null;
}
- String doi = mint(context, dso, skipFilter);
+ String doi = mint(context, dso, filter);
// register tries to reserve doi if it's not already.
// So we don't have to reserve it here.
- register(context, dso, doi, skipFilter);
+ register(context, dso, doi, filter);
return doi;
}
@@ -250,11 +269,11 @@ public String register(Context context, DSpaceObject dso, boolean skipFilter)
* @param context - DSpace context
* @param dso - DSpaceObject identified by the new DOI
* @param identifier - String containing the DOI to register
- * @param skipFilter - boolean indicating whether to skip any filtering of items before performing registration
+ * @param filter - Logical item filter to determine whether this identifier should be registered
* @throws IdentifierException
*/
@Override
- public void register(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
+ public void register(Context context, DSpaceObject dso, String identifier, Filter filter)
throws IdentifierException {
if (!(dso instanceof Item)) {
// DOI are currently assigned only to Item
@@ -265,7 +284,7 @@ public void register(Context context, DSpaceObject dso, String identifier, boole
// search DOI in our db
try {
- doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
+ doiRow = loadOrCreateDOI(context, dso, doi, filter);
} catch (SQLException ex) {
log.error("Error in databse connection: " + ex.getMessage());
throw new RuntimeException("Error in database conncetion.", ex);
@@ -277,7 +296,6 @@ public void register(Context context, DSpaceObject dso, String identifier, boole
+ "is marked as DELETED.", DOIIdentifierException.DOI_IS_DELETED);
}
- // Check status of DOI
if (IS_REGISTERED.equals(doiRow.getStatus())) {
return;
}
@@ -290,6 +308,7 @@ public void register(Context context, DSpaceObject dso, String identifier, boole
log.warn("SQLException while changing status of DOI {} to be registered.", doi);
throw new RuntimeException(sqle);
}
+
}
/**
@@ -309,7 +328,7 @@ public void register(Context context, DSpaceObject dso, String identifier, boole
@Override
public void reserve(Context context, DSpaceObject dso, String identifier)
throws IdentifierException, IllegalArgumentException {
- reserve(context, dso, identifier, false);
+ reserve(context, dso, identifier, this.filter);
}
/**
@@ -317,20 +336,18 @@ public void reserve(Context context, DSpaceObject dso, String identifier)
* @param context - DSpace context
* @param dso - DSpaceObject identified by this DOI
* @param identifier - String containing the DOI to reserve
- * @param skipFilter - boolean indicating whether to skip any filtering of items before performing reservation
+ * @param filter - Logical item filter to determine whether this identifier should be reserved
* @throws IdentifierException
* @throws IllegalArgumentException
*/
@Override
- public void reserve(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
+ public void reserve(Context context, DSpaceObject dso, String identifier, Filter filter)
throws IdentifierException, IllegalArgumentException {
String doi = doiService.formatIdentifier(identifier);
DOI doiRow = null;
try {
- // if the doi is in our db already loadOrCreateDOI just returns.
- // if it is not loadOrCreateDOI safes the doi.
- doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
+ doiRow = loadOrCreateDOI(context, dso, doi, filter);
} catch (SQLException sqle) {
throw new RuntimeException(sqle);
}
@@ -359,7 +376,7 @@ public void reserve(Context context, DSpaceObject dso, String identifier, boolea
*/
public void reserveOnline(Context context, DSpaceObject dso, String identifier)
throws IdentifierException, IllegalArgumentException, SQLException {
- reserveOnline(context, dso, identifier, false);
+ reserveOnline(context, dso, identifier, this.filter);
}
/**
@@ -367,16 +384,16 @@ public void reserveOnline(Context context, DSpaceObject dso, String identifier)
* @param context - DSpace context
* @param dso - DSpaceObject identified by this DOI
* @param identifier - String containing the DOI to reserve
- * @param skipFilter - skip the filters for {@link checkMintable(Context, DSpaceObject)}
+ * @param filter - Logical item filter to determine whether this identifier should be reserved online
* @throws IdentifierException
* @throws IllegalArgumentException
* @throws SQLException
*/
- public void reserveOnline(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
+ public void reserveOnline(Context context, DSpaceObject dso, String identifier, Filter filter)
throws IdentifierException, IllegalArgumentException, SQLException {
String doi = doiService.formatIdentifier(identifier);
// get TableRow and ensure DOI belongs to dso regarding our db
- DOI doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
+ DOI doiRow = loadOrCreateDOI(context, dso, doi, filter);
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
throw new DOIIdentifierException("You tried to reserve a DOI that "
@@ -402,7 +419,7 @@ public void reserveOnline(Context context, DSpaceObject dso, String identifier,
public void registerOnline(Context context, DSpaceObject dso, String identifier)
throws IdentifierException, IllegalArgumentException, SQLException {
- registerOnline(context, dso, identifier, false);
+ registerOnline(context, dso, identifier, this.filter);
}
@@ -411,18 +428,17 @@ public void registerOnline(Context context, DSpaceObject dso, String identifier)
* @param context - DSpace context
* @param dso - DSpaceObject identified by this DOI
* @param identifier - String containing the DOI to register
- * @param skipFilter - skip filters for {@link checkMintable(Context, DSpaceObject)}
+ * @param filter - Logical item filter to determine whether this identifier should be registered online
* @throws IdentifierException
* @throws IllegalArgumentException
* @throws SQLException
*/
- public void registerOnline(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
+ public void registerOnline(Context context, DSpaceObject dso, String identifier, Filter filter)
throws IdentifierException, IllegalArgumentException, SQLException {
- log.debug("registerOnline: skipFilter is " + skipFilter);
String doi = doiService.formatIdentifier(identifier);
// get TableRow and ensure DOI belongs to dso regarding our db
- DOI doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
+ DOI doiRow = loadOrCreateDOI(context, dso, doi, filter);
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
throw new DOIIdentifierException("You tried to register a DOI that "
@@ -435,7 +451,7 @@ public void registerOnline(Context context, DSpaceObject dso, String identifier,
} catch (DOIIdentifierException die) {
// do we have to reserve DOI before we can register it?
if (die.getCode() == DOIIdentifierException.RESERVE_FIRST) {
- this.reserveOnline(context, dso, identifier, skipFilter);
+ this.reserveOnline(context, dso, identifier, filter);
connector.registerDOI(context, dso, doi);
} else {
throw die;
@@ -471,17 +487,23 @@ public void updateMetadata(Context context, DSpaceObject dso, String identifier)
throws IdentifierException, IllegalArgumentException, SQLException {
String doi = doiService.formatIdentifier(identifier);
-
- boolean skipFilter = false;
+ // Use the default filter unless we find the object
+ Filter updateFilter = this.filter;
if (doiService.findDOIByDSpaceObject(context, dso) != null) {
// We can skip the filter here since we know the DOI already exists for the item
log.debug("updateMetadata: found DOIByDSpaceObject: " +
doiService.findDOIByDSpaceObject(context, dso).getDoi());
- skipFilter = true;
+ updateFilter = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
+ "always_true_filter", TrueFilter.class);
}
- DOI doiRow = loadOrCreateDOI(context, dso, doi, skipFilter);
+ DOI doiRow = loadOrCreateDOI(context, dso, doi, updateFilter);
+
+ if (PENDING.equals(doiRow.getStatus()) || MINTED.equals(doiRow.getStatus())) {
+ log.info("Not updating metadata for PENDING or MINTED doi: " + doi);
+ return;
+ }
if (DELETED.equals(doiRow.getStatus()) || TO_BE_DELETED.equals(doiRow.getStatus())) {
throw new DOIIdentifierException("You tried to register a DOI that "
@@ -571,19 +593,19 @@ public void updateMetadataOnline(Context context, DSpaceObject dso, String ident
@Override
public String mint(Context context, DSpaceObject dso)
throws IdentifierException {
- return mint(context, dso, false);
+ return mint(context, dso, this.filter);
}
/**
* Mint a new DOI in DSpace - this is usually the first step of registration
* @param context - DSpace context
* @param dso - DSpaceObject identified by the new identifier
- * @param skipFilter - boolean indicating whether to skip any filtering of items before minting.
+ * @param filter - Logical item filter to determine whether this identifier should be registered
* @return a String containing the new identifier
* @throws IdentifierException
*/
@Override
- public String mint(Context context, DSpaceObject dso, boolean skipFilter) throws IdentifierException {
+ public String mint(Context context, DSpaceObject dso, Filter filter) throws IdentifierException {
String doi = null;
try {
@@ -597,7 +619,7 @@ public String mint(Context context, DSpaceObject dso, boolean skipFilter) throws
}
if (null == doi) {
try {
- DOI doiRow = loadOrCreateDOI(context, dso, null, skipFilter);
+ DOI doiRow = loadOrCreateDOI(context, dso, null, filter);
doi = DOI.SCHEME + doiRow.getDoi();
} catch (SQLException e) {
@@ -895,7 +917,7 @@ public String getDOIByObject(Context context, DSpaceObject dso) throws SQLExcept
*/
protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdentifier)
throws SQLException, DOIIdentifierException, IdentifierNotApplicableException {
- return loadOrCreateDOI(context, dso, doiIdentifier, false);
+ return loadOrCreateDOI(context, dso, doiIdentifier, this.filter);
}
/**
@@ -910,13 +932,13 @@ protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdent
* @param context - DSpace context
* @param dso - DSpaceObject to identify
* @param doiIdentifier - DOI to load or create (null to mint a new one)
- * @param skipFilter - Whether or not to skip the filters for the checkMintable() check
+ * @param filter - Logical item filter to determine whether this identifier should be registered
* @return
* @throws SQLException
* @throws DOIIdentifierException
* @throws org.dspace.identifier.IdentifierNotApplicableException passed through.
*/
- protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdentifier, boolean skipFilter)
+ protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdentifier, Filter filter)
throws SQLException, DOIIdentifierException, IdentifierNotApplicableException {
DOI doi = null;
@@ -954,6 +976,8 @@ protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdent
// doi is assigned to a DSO; is it assigned to our specific dso?
// check if DOI already belongs to dso
if (dso.getID().equals(doi.getDSpaceObject().getID())) {
+ // Before we return this, check the filter
+ checkMintable(context, filter, dso);
return doi;
} else {
throw new DOIIdentifierException("Trying to create a DOI " +
@@ -963,15 +987,8 @@ protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdent
}
}
- // we did not find the doi in the database or shall reassign it. Before doing so, we should check if a
- // filter is in place to prevent the creation of new DOIs for certain items.
- if (skipFilter) {
- log.warn("loadOrCreateDOI: Skipping default item filter");
- } else {
- // Find out if we're allowed to create a DOI
- // throws an exception if creation of a new DOI is prohibited by a filter
- checkMintable(context, dso);
- }
+ // Check if this item is eligible for minting. An IdentifierNotApplicableException will be thrown if not.
+ checkMintable(context, filter, dso);
// check prefix
if (!doiIdentifier.startsWith(this.getPrefix() + "/")) {
@@ -984,15 +1001,8 @@ protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdent
doi = doiService.create(context);
}
} else {
- // We need to generate a new DOI. Before doing so, we should check if a
- // filter is in place to prevent the creation of new DOIs for certain items.
- if (skipFilter) {
- log.warn("loadOrCreateDOI: Skipping default item filter");
- } else {
- // Find out if we're allowed to create a DOI
- // throws an exception if creation of a new DOI is prohibited by a filter
- checkMintable(context, dso);
- }
+ // Check if this item is eligible for minting. An IdentifierNotApplicableException will be thrown if not.
+ checkMintable(context, filter, dso);
doi = doiService.create(context);
doiIdentifier = this.getPrefix() + "/" + this.getNamespaceSeparator() +
@@ -1002,7 +1012,7 @@ protected DOI loadOrCreateDOI(Context context, DSpaceObject dso, String doiIdent
// prepare new doiRow
doi.setDoi(doiIdentifier);
doi.setDSpaceObject(dso);
- doi.setStatus(null);
+ doi.setStatus(MINTED);
try {
doiService.update(context, doi);
} catch (SQLException e) {
@@ -1102,20 +1112,32 @@ protected void removeDOIFromObject(Context context, DSpaceObject dso, String doi
/**
* Checks to see if an item can have a DOI minted, using the configured logical filter
* @param context
+ * @param filter Logical item filter to apply
* @param dso The item to be evaluated
* @throws DOIIdentifierNotApplicableException
*/
@Override
- public void checkMintable(Context context, DSpaceObject dso) throws DOIIdentifierNotApplicableException {
+ public void checkMintable(Context context, Filter filter, DSpaceObject dso)
+ throws DOIIdentifierNotApplicableException {
+ if (filter == null) {
+ Filter trueFilter = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
+ "always_true_filter", TrueFilter.class);
+ // If a null filter was passed, and we have a good default filter to apply, apply it.
+ // Otherwise, set to TrueFilter which means "no filtering"
+ if (this.filter != null) {
+ filter = this.filter;
+ } else {
+ filter = trueFilter;
+ }
+ }
// If the check fails, an exception will be thrown to be caught by the calling method
- if (this.filterService != null && contentServiceFactory
- .getDSpaceObjectService(dso).getTypeText(dso).equals("ITEM")) {
+ if (contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso).equals("ITEM")) {
try {
- boolean result = filterService.getResult(context, (Item) dso);
+ boolean result = filter.getResult(context, (Item) dso);
log.debug("Result of filter for " + dso.getHandle() + " is " + result);
if (!result) {
throw new DOIIdentifierNotApplicableException("Item " + dso.getHandle() +
- " was evaluated as 'false' by the item filter, not minting");
+ " was evaluated as 'false' by the item filter, not minting");
}
} catch (LogicalStatementException e) {
log.error("Error evaluating item with logical filter: " + e.getLocalizedMessage());
@@ -1125,4 +1147,16 @@ public void checkMintable(Context context, DSpaceObject dso) throws DOIIdentifie
log.debug("DOI Identifier Provider: filterService is null (ie. don't prevent DOI minting)");
}
}
+
+ /**
+ * Checks to see if an item can have a DOI minted, using the configured logical filter
+ * @param context
+ * @param dso The item to be evaluated
+ * @throws DOIIdentifierNotApplicableException
+ */
+ @Override
+ public void checkMintable(Context context, DSpaceObject dso) throws DOIIdentifierNotApplicableException {
+ checkMintable(context, this.filter, dso);
+ }
+
}
\ No newline at end of file
diff --git a/dspace-api/src/main/java/org/dspace/identifier/FilteredIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/FilteredIdentifierProvider.java
index fdc7c1db23f5..c2254fa9a6fd 100644
--- a/dspace-api/src/main/java/org/dspace/identifier/FilteredIdentifierProvider.java
+++ b/dspace-api/src/main/java/org/dspace/identifier/FilteredIdentifierProvider.java
@@ -12,8 +12,9 @@
import org.dspace.content.DSpaceObject;
import org.dspace.content.logic.Filter;
+import org.dspace.content.logic.TrueFilter;
import org.dspace.core.Context;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.dspace.services.factory.DSpaceServicesFactory;
/**
* This abstract class adds extra method signatures so that implementing IdentifierProviders can
@@ -24,26 +25,28 @@
*/
public abstract class FilteredIdentifierProvider extends IdentifierProvider {
- protected Filter filterService;
+ protected Filter filter = DSpaceServicesFactory.getInstance()
+ .getServiceManager().getServiceByName("always_true_filter", TrueFilter.class);
/**
- * Setter for spring to set the filter service from the property in configuration XML
- * @param filterService - an object implementing the org.dspace.content.logic.Filter interface
+ * Setter for spring to set the default filter from the property in configuration XML
+ * @param filter - an object implementing the org.dspace.content.logic.Filter interface
*/
- @Autowired
- public void setFilterService(Filter filterService) {
- this.filterService = filterService;
+ public void setFilter(Filter filter) {
+ if (filter != null) {
+ this.filter = filter;
+ }
}
/**
* Register a new identifier for a given DSpaceObject
* @param context - DSpace context
* @param dso - DSpaceObject to use for identifier registration
- * @param skipFilter - boolean indicating whether to skip any filtering of items before performing registration
+ * @param filter - Logical item filter to determine whether this identifier should be registered
* @return identifier
* @throws IdentifierException
*/
- public abstract String register(Context context, DSpaceObject dso, boolean skipFilter)
+ public abstract String register(Context context, DSpaceObject dso, Filter filter)
throws IdentifierException;
/**
@@ -51,10 +54,10 @@ public abstract String register(Context context, DSpaceObject dso, boolean skipF
* @param context - DSpace context
* @param dso - DSpaceObject identified by the new identifier
* @param identifier - String containing the identifier to register
- * @param skipFilter - boolean indicating whether to skip any filtering of items before performing registration
+ * @param filter - Logical item filter to determine whether this identifier should be registered
* @throws IdentifierException
*/
- public abstract void register(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
+ public abstract void register(Context context, DSpaceObject dso, String identifier, Filter filter)
throws IdentifierException;
/**
@@ -62,23 +65,23 @@ public abstract void register(Context context, DSpaceObject dso, String identifi
* @param context - DSpace context
* @param dso - DSpaceObject identified by this identifier
* @param identifier - String containing the identifier to reserve
- * @param skipFilter - boolean indicating whether to skip any filtering of items before performing reservation
+ * @param filter - Logical item filter to determine whether this identifier should be reserved
* @throws IdentifierException
* @throws IllegalArgumentException
* @throws SQLException
*/
- public abstract void reserve(Context context, DSpaceObject dso, String identifier, boolean skipFilter)
+ public abstract void reserve(Context context, DSpaceObject dso, String identifier, Filter filter)
throws IdentifierException, IllegalArgumentException, SQLException;
/**
* Mint a new identifier in DSpace - this is usually the first step of registration
* @param context - DSpace context
* @param dso - DSpaceObject identified by the new identifier
- * @param skipFilter - boolean indicating whether to skip any filtering of items before minting
+ * @param filter - Logical item filter to determine whether this identifier should be registered
* @return a String containing the new identifier
* @throws IdentifierException
*/
- public abstract String mint(Context context, DSpaceObject dso, boolean skipFilter) throws IdentifierException;
+ public abstract String mint(Context context, DSpaceObject dso, Filter filter) throws IdentifierException;
/**
* Check configured item filters to see if this identifier is allowed to be minted
@@ -88,5 +91,13 @@ public abstract void reserve(Context context, DSpaceObject dso, String identifie
*/
public abstract void checkMintable(Context context, DSpaceObject dso) throws IdentifierException;
+ /**
+ * Check configured item filters to see if this identifier is allowed to be minted
+ * @param context - DSpace context
+ * @param filter - Logical item filter
+ * @param dso - DSpaceObject to be inspected
+ * @throws IdentifierException
+ */
+ public abstract void checkMintable(Context context, Filter filter, DSpaceObject dso) throws IdentifierException;
}
diff --git a/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java b/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java
index 1a43595391ab..412baba6a8da 100644
--- a/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java
@@ -10,6 +10,7 @@
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
@@ -17,6 +18,7 @@
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
import org.dspace.content.factory.ContentServiceFactory;
+import org.dspace.content.logic.Filter;
import org.dspace.core.Context;
import org.dspace.handle.service.HandleService;
import org.dspace.identifier.service.IdentifierService;
@@ -44,7 +46,6 @@ public class IdentifierServiceImpl implements IdentifierService {
protected HandleService handleService;
protected IdentifierServiceImpl() {
-
}
@Autowired(required = true)
@@ -98,7 +99,7 @@ public void reserve(Context context, DSpaceObject dso, String identifier)
@Override
public void register(Context context, DSpaceObject dso)
- throws AuthorizeException, SQLException, IdentifierException {
+ throws AuthorizeException, SQLException, IdentifierException {
//We need to commit our context because one of the providers might require the handle created above
// Next resolve all other services
for (IdentifierProvider service : providers) {
@@ -112,11 +113,99 @@ public void register(Context context, DSpaceObject dso)
contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
}
+ @Override
+ public void register(Context context, DSpaceObject dso, Class extends Identifier> type, Filter filter)
+ throws AuthorizeException, SQLException, IdentifierException {
+ boolean registered = false;
+ // Iterate all services and register identifiers as appropriate
+ for (IdentifierProvider service : providers) {
+ if (service.supports(type)) {
+ try {
+ if (service instanceof FilteredIdentifierProvider) {
+ FilteredIdentifierProvider filteredService = (FilteredIdentifierProvider)service;
+ filteredService.register(context, dso, filter);
+ } else {
+ service.register(context, dso);
+ }
+ registered = true;
+ } catch (IdentifierNotApplicableException e) {
+ log.warn("Identifier not registered (inapplicable): " + e.getMessage());
+ }
+ }
+ }
+ if (!registered) {
+ throw new IdentifierException("Cannot register identifier: Didn't "
+ + "find a provider that supports this identifier.");
+ }
+ // Update our item / collection / community
+ contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
+ }
+
+ @Override
+ public void register(Context context, DSpaceObject dso, Class extends Identifier> type)
+ throws AuthorizeException, SQLException, IdentifierException {
+ boolean registered = false;
+ // Iterate all services and register identifiers as appropriate
+ for (IdentifierProvider service : providers) {
+ if (service.supports(type)) {
+ try {
+ service.register(context, dso);
+ registered = true;
+ } catch (IdentifierNotApplicableException e) {
+ log.warn("Identifier not registered (inapplicable): " + e.getMessage());
+ }
+ }
+ }
+ if (!registered) {
+ throw new IdentifierException("Cannot register identifier: Didn't "
+ + "find a provider that supports this identifier.");
+ }
+ // Update our item / collection / community
+ contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
+ }
+
+ @Override
+ public void register(Context context, DSpaceObject dso, Map, Filter> typeFilters)
+ throws AuthorizeException, SQLException, IdentifierException {
+ // Iterate all services and register identifiers as appropriate
+ for (IdentifierProvider service : providers) {
+ try {
+ // If the service supports filtering, look through the map and the first supported class
+ // we find, set the filter and break. If no filter was seen for this type, just let the provider
+ // use its own implementation.
+ if (service instanceof FilteredIdentifierProvider) {
+ FilteredIdentifierProvider filteredService = (FilteredIdentifierProvider)service;
+ Filter filter = null;
+ for (Class extends Identifier> type : typeFilters.keySet()) {
+ if (filteredService.supports(type)) {
+ filter = typeFilters.get(type);
+ break;
+ }
+ }
+ if (filter != null) {
+ // Pass the found filter to the provider
+ filteredService.register(context, dso, filter);
+ } else {
+ // Let the provider use the default filter / behaviour
+ filteredService.register(context, dso);
+ }
+ } else {
+ service.register(context, dso);
+ }
+ } catch (IdentifierNotApplicableException e) {
+ log.warn("Identifier not registered (inapplicable): " + e.getMessage());
+ }
+ }
+ // Update our item / collection / community
+ contentServiceFactory.getDSpaceObjectService(dso).update(context, dso);
+ }
+
+
+
@Override
public void register(Context context, DSpaceObject object, String identifier)
throws AuthorizeException, SQLException, IdentifierException {
- //We need to commit our context because one of the providers might require the handle created above
- // Next resolve all other services
+ // Iterate all services and register identifiers as appropriate
boolean registered = false;
for (IdentifierProvider service : providers) {
if (service.supports(identifier)) {
@@ -132,7 +221,7 @@ public void register(Context context, DSpaceObject object, String identifier)
throw new IdentifierException("Cannot register identifier: Didn't "
+ "find a provider that supports this identifier.");
}
- //Update our item / collection / community
+ // pdate our item / collection / community
contentServiceFactory.getDSpaceObjectService(object).update(context, object);
}
diff --git a/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java
index a864b4be4bf2..e7c786d5f8ce 100644
--- a/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java
+++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedDOIIdentifierProvider.java
@@ -18,6 +18,7 @@
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.MetadataValue;
+import org.dspace.content.logic.Filter;
import org.dspace.core.Context;
import org.dspace.identifier.doi.DOIConnector;
import org.dspace.identifier.doi.DOIIdentifierException;
@@ -49,7 +50,12 @@ public class VersionedDOIIdentifierProvider extends DOIIdentifierProvider {
protected VersionHistoryService versionHistoryService;
@Override
- public String mint(Context context, DSpaceObject dso)
+ public String mint(Context context, DSpaceObject dso) throws IdentifierException {
+ return mint(context, dso, this.filter);
+ }
+
+ @Override
+ public String mint(Context context, DSpaceObject dso, Filter filter)
throws IdentifierException {
if (!(dso instanceof Item)) {
throw new IdentifierException("Currently only Items are supported for DOIs.");
@@ -79,6 +85,9 @@ public String mint(Context context, DSpaceObject dso)
+ " with ID " + dso.getID() + ".", ex);
}
+ // Make a call to the filter here to throw an exception instead of carrying on with removal + creation
+ checkMintable(context, filter, dso);
+
// check whether we have a DOI in the metadata and if we have to remove it
String metadataDOI = getDOIOutOfObject(dso);
if (metadataDOI != null) {
@@ -111,7 +120,7 @@ public String mint(Context context, DSpaceObject dso)
// ensure DOI exists in our database as well and return.
// this also checks that the doi is not assigned to another dso already.
try {
- loadOrCreateDOI(context, dso, versionedDOI);
+ loadOrCreateDOI(context, dso, versionedDOI, filter);
} catch (SQLException ex) {
log.error(
"A problem with the database connection occurd while processing DOI " + versionedDOI + ".", ex);
@@ -127,7 +136,7 @@ public String mint(Context context, DSpaceObject dso)
// if we have a history, we have a item
doi = makeIdentifierBasedOnHistory(context, dso, history);
} else {
- doi = loadOrCreateDOI(context, dso, null).getDoi();
+ doi = loadOrCreateDOI(context, dso, null, filter).getDoi();
}
} catch (SQLException ex) {
log.error("SQLException while creating a new DOI: ", ex);
@@ -140,7 +149,12 @@ public String mint(Context context, DSpaceObject dso)
}
@Override
- public void register(Context context, DSpaceObject dso, String identifier)
+ public void register(Context context, DSpaceObject dso, String identifier) throws IdentifierException {
+ register(context, dso, identifier, this.filter);
+ }
+
+ @Override
+ public void register(Context context, DSpaceObject dso, String identifier, Filter filter)
throws IdentifierException {
if (!(dso instanceof Item)) {
throw new IdentifierException("Currently only Items are supported for DOIs.");
@@ -220,8 +234,14 @@ protected String getDOIPostfix(String identifier)
return doiPostfix;
}
- // Should never return null!
protected String makeIdentifierBasedOnHistory(Context context, DSpaceObject dso, VersionHistory history)
+ throws AuthorizeException, SQLException, DOIIdentifierException, IdentifierNotApplicableException {
+ return makeIdentifierBasedOnHistory(context, dso, history, this.filter);
+ }
+
+ // Should never return null!
+ protected String makeIdentifierBasedOnHistory(Context context, DSpaceObject dso, VersionHistory history,
+ Filter filter)
throws AuthorizeException, SQLException, DOIIdentifierException, IdentifierNotApplicableException {
// Mint foreach new version an identifier like: 12345/100.versionNumber
// use the bare handle (g.e. 12345/100) for the first version.
@@ -244,6 +264,9 @@ protected String makeIdentifierBasedOnHistory(Context context, DSpaceObject dso,
}
if (previousVersionDOI == null) {
+ // Before continuing with any new DOI creation, apply the filter
+ checkMintable(context, filter, dso);
+
// We need to generate a new DOI.
DOI doi = doiService.create(context);
@@ -269,7 +292,7 @@ protected String makeIdentifierBasedOnHistory(Context context, DSpaceObject dso,
String.valueOf(versionHistoryService.getVersion(context, history, item).getVersionNumber()));
}
- loadOrCreateDOI(context, dso, identifier);
+ loadOrCreateDOI(context, dso, identifier, filter);
return identifier;
}
diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConsumer.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConsumer.java
index 654d275d8725..1961ce82744c 100644
--- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConsumer.java
+++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConsumer.java
@@ -7,22 +7,32 @@
*/
package org.dspace.identifier.doi;
+import java.sql.SQLException;
+
import org.apache.logging.log4j.Logger;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.factory.ContentServiceFactory;
+import org.dspace.content.logic.Filter;
+import org.dspace.content.logic.FilterUtils;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.event.Consumer;
import org.dspace.event.Event;
+import org.dspace.identifier.DOI;
import org.dspace.identifier.DOIIdentifierProvider;
import org.dspace.identifier.IdentifierException;
-import org.dspace.identifier.IdentifierNotFoundException;
+import org.dspace.identifier.IdentifierNotApplicableException;
+import org.dspace.identifier.factory.IdentifierServiceFactory;
+import org.dspace.identifier.service.DOIService;
+import org.dspace.services.ConfigurationService;
+import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.utils.DSpace;
import org.dspace.workflow.factory.WorkflowServiceFactory;
/**
* @author Pascal-Nicolas Becker (p dot becker at tu hyphen berlin dot de)
+ * @author Kim Shepherd
*/
public class DOIConsumer implements Consumer {
/**
@@ -30,12 +40,15 @@ public class DOIConsumer implements Consumer {
*/
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(DOIConsumer.class);
+ ConfigurationService configurationService;
+
@Override
public void initialize() throws Exception {
// nothing to do
// we can ask spring to give as a properly setuped instance of
// DOIIdentifierProvider. Doing so we don't have to configure it and
// can load it in consume method as this is not very expensive.
+ configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
}
@@ -62,36 +75,73 @@ public void consume(Context ctx, Event event) throws Exception {
return;
}
Item item = (Item) dso;
+ DOIIdentifierProvider provider = new DSpace().getSingletonService(DOIIdentifierProvider.class);
+ boolean inProgress = (ContentServiceFactory.getInstance().getWorkspaceItemService().findByItem(ctx, item)
+ != null || WorkflowServiceFactory.getInstance().getWorkflowItemService().findByItem(ctx, item) != null);
+ boolean identifiersInSubmission = configurationService.getBooleanProperty("identifiers.submission.register",
+ false);
+ DOIService doiService = IdentifierServiceFactory.getInstance().getDOIService();
+ Filter workspaceFilter = null;
+ if (identifiersInSubmission) {
+ workspaceFilter = FilterUtils.getFilterFromConfiguration("identifiers.submission.filter.workspace");
+ }
- if (ContentServiceFactory.getInstance().getWorkspaceItemService().findByItem(ctx, item) != null
- || WorkflowServiceFactory.getInstance().getWorkflowItemService().findByItem(ctx, item) != null) {
- // ignore workflow and workspace items, DOI will be minted when item is installed
+ if (inProgress && !identifiersInSubmission) {
+ // ignore workflow and workspace items, DOI will be minted and updated when item is installed
+ // UNLESS special pending filter is set
return;
}
-
- DOIIdentifierProvider provider = new DSpace().getSingletonService(
- DOIIdentifierProvider.class);
-
- String doi = null;
+ DOI doi = null;
try {
- doi = provider.lookup(ctx, dso);
- } catch (IdentifierNotFoundException ex) {
+ doi = doiService.findDOIByDSpaceObject(ctx, dso);
+ } catch (SQLException ex) {
// nothing to do here, next if clause will stop us from processing
// items without dois.
}
if (doi == null) {
- log.debug("DOIConsumer cannot handles items without DOIs, skipping: "
- + event.toString());
- return;
- }
- try {
- provider.updateMetadata(ctx, dso, doi);
- } catch (IllegalArgumentException ex) {
- // should not happen, as we got the DOI from the DOIProvider
- log.warn("DOIConsumer caught an IdentifierException.", ex);
- } catch (IdentifierException ex) {
- log.warn("DOIConsumer cannot update metadata for Item with ID "
- + item.getID() + " and DOI " + doi + ".", ex);
+ // No DOI. The only time something should be minted is if we have enabled submission reg'n and
+ // it passes the workspace filter. We also need to update status to PENDING straight after.
+ if (inProgress) {
+ provider.mint(ctx, dso, workspaceFilter);
+ DOI newDoi = doiService.findDOIByDSpaceObject(ctx, dso);
+ if (newDoi != null) {
+ newDoi.setStatus(DOIIdentifierProvider.PENDING);
+ doiService.update(ctx, newDoi);
+ }
+ } else {
+ log.debug("DOIConsumer cannot handles items without DOIs, skipping: " + event.toString());
+ }
+ } else {
+ // If in progress, we can also switch PENDING and MINTED status depending on the latest filter
+ // evaluation
+ if (inProgress) {
+ try {
+ // Check the filter
+ provider.checkMintable(ctx, workspaceFilter, dso);
+ // If we made it here, the existing doi should be back to PENDING
+ if (DOIIdentifierProvider.MINTED.equals(doi.getStatus())) {
+ doi.setStatus(DOIIdentifierProvider.PENDING);
+ }
+ } catch (IdentifierNotApplicableException e) {
+ // Set status to MINTED if configured to downgrade existing DOIs
+ if (configurationService
+ .getBooleanProperty("identifiers.submission.strip_pending_during_submission", true)) {
+ doi.setStatus(DOIIdentifierProvider.MINTED);
+ }
+ }
+ doiService.update(ctx, doi);
+ } else {
+ try {
+ provider.updateMetadata(ctx, dso, doi.getDoi());
+ } catch (IllegalArgumentException ex) {
+ // should not happen, as we got the DOI from the DOIProvider
+ log.warn("DOIConsumer caught an IdentifierException.", ex);
+ } catch (IdentifierException ex) {
+ log.warn("DOIConsumer cannot update metadata for Item with ID "
+ + item.getID() + " and DOI " + doi + ".", ex);
+ }
+ }
+ ctx.commit();
}
}
diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java
index 4cc8b77ddcfd..ad885314bb2b 100644
--- a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java
+++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java
@@ -30,6 +30,9 @@
import org.apache.logging.log4j.Logger;
import org.dspace.content.DSpaceObject;
import org.dspace.content.factory.ContentServiceFactory;
+import org.dspace.content.logic.Filter;
+import org.dspace.content.logic.FilterUtils;
+import org.dspace.content.logic.TrueFilter;
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
@@ -65,6 +68,9 @@ public class DOIOrganiser {
protected boolean skipFilter;
+ // This filter will override the default provider filter / behaviour
+ protected Filter filter;
+
/**
* Constructor to be called within the main() method
* @param context - DSpace context
@@ -78,7 +84,8 @@ public DOIOrganiser(Context context, DOIIdentifierProvider provider) {
this.itemService = ContentServiceFactory.getInstance().getItemService();
this.doiService = IdentifierServiceFactory.getInstance().getDOIService();
this.configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
- this.skipFilter = false;
+ this.filter = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
+ "always_true_filter", TrueFilter.class);
}
/**
@@ -123,12 +130,13 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args
"Perform online metadata update for all identifiers queued for metadata update.");
options.addOption("d", "delete-all", false,
"Perform online deletion for all identifiers queued for deletion.");
-
options.addOption("q", "quiet", false,
"Turn the command line output off.");
- options.addOption(null, "skip-filter", false,
- "Skip the configured item filter when registering or reserving.");
+ Option filterDoi = Option.builder().optionalArg(true).longOpt("filter").hasArg().argName("filterName")
+ .desc("Use the specified filter name instead of the provider's filter. Defaults to a special " +
+ "'always true' filter to force operations").build();
+ options.addOption(filterDoi);
Option registerDoi = Option.builder()
.longOpt("register-doi")
@@ -205,10 +213,12 @@ public static void runCLI(Context context, DOIOrganiser organiser, String[] args
}
DOIService doiService = IdentifierServiceFactory.getInstance().getDOIService();
- // Should we skip the filter?
- if (line.hasOption("skip-filter")) {
- System.out.println("Skipping the item filter");
- organiser.skipFilter = true;
+ // Do we get a filter?
+ if (line.hasOption("filter")) {
+ String filter = line.getOptionValue("filter");
+ if (null != filter) {
+ organiser.filter = FilterUtils.getFilterFromConfiguration(filter);
+ }
}
if (line.hasOption('s')) {
@@ -396,19 +406,18 @@ public void list(String processName, PrintStream out, PrintStream err, Integer .
/**
* Register DOI with the provider
* @param doiRow - doi to register
- * @param skipFilter - whether filters should be skipped before registration
+ * @param filter - logical item filter to override
* @throws SQLException
* @throws DOIIdentifierException
*/
- public void register(DOI doiRow, boolean skipFilter) throws SQLException, DOIIdentifierException {
+ public void register(DOI doiRow, Filter filter) throws SQLException, DOIIdentifierException {
DSpaceObject dso = doiRow.getDSpaceObject();
if (Constants.ITEM != dso.getType()) {
throw new IllegalArgumentException("Currenty DSpace supports DOIs for Items only.");
}
try {
- provider.registerOnline(context, dso,
- DOI.SCHEME + doiRow.getDoi());
+ provider.registerOnline(context, dso, DOI.SCHEME + doiRow.getDoi(), filter);
if (!quiet) {
System.out.println("This identifier: "
@@ -468,29 +477,23 @@ public void register(DOI doiRow, boolean skipFilter) throws SQLException, DOIIde
}
/**
- * Register DOI with the provider, always applying (ie. never skipping) any configured filters
+ * Register DOI with the provider
* @param doiRow - doi to register
* @throws SQLException
* @throws DOIIdentifierException
*/
public void register(DOI doiRow) throws SQLException, DOIIdentifierException {
- if (this.skipFilter) {
- System.out.println("Skipping the filter for " + doiRow.getDoi());
- }
- register(doiRow, this.skipFilter);
+ register(doiRow, this.filter);
}
/**
- * Reserve DOI with the provider, always applying (ie. never skipping) any configured filters
+ * Reserve DOI with the provider,
* @param doiRow - doi to reserve
* @throws SQLException
* @throws DOIIdentifierException
*/
public void reserve(DOI doiRow) {
- if (this.skipFilter) {
- System.out.println("Skipping the filter for " + doiRow.getDoi());
- }
- reserve(doiRow, this.skipFilter);
+ reserve(doiRow, this.filter);
}
/**
@@ -499,14 +502,14 @@ public void reserve(DOI doiRow) {
* @throws SQLException
* @throws DOIIdentifierException
*/
- public void reserve(DOI doiRow, boolean skipFilter) {
+ public void reserve(DOI doiRow, Filter filter) {
DSpaceObject dso = doiRow.getDSpaceObject();
if (Constants.ITEM != dso.getType()) {
throw new IllegalArgumentException("Currently DSpace supports DOIs for Items only.");
}
try {
- provider.reserveOnline(context, dso, DOI.SCHEME + doiRow.getDoi(), skipFilter);
+ provider.reserveOnline(context, dso, DOI.SCHEME + doiRow.getDoi(), filter);
if (!quiet) {
System.out.println("This identifier : " + DOI.SCHEME + doiRow.getDoi() + " is successfully reserved.");
@@ -701,7 +704,7 @@ public DOI resolveToDOI(String identifier)
//Check if this Item has an Identifier, mint one if it doesn't
if (null == doiRow) {
- doi = provider.mint(context, dso, this.skipFilter);
+ doi = provider.mint(context, dso, this.filter);
doiRow = doiService.findByDoi(context,
doi.substring(DOI.SCHEME.length()));
return doiRow;
@@ -725,7 +728,7 @@ public DOI resolveToDOI(String identifier)
doiRow = doiService.findDOIByDSpaceObject(context, dso);
if (null == doiRow) {
- doi = provider.mint(context, dso, this.skipFilter);
+ doi = provider.mint(context, dso, this.filter);
doiRow = doiService.findByDoi(context,
doi.substring(DOI.SCHEME.length()));
}
diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java
index 57136d6143bb..43882918cd4a 100644
--- a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java
+++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java
@@ -8,13 +8,14 @@
package org.dspace.identifier.doi;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.sql.SQLException;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
@@ -35,13 +36,14 @@
import org.apache.http.util.EntityUtils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
+import org.dspace.content.Item;
import org.dspace.content.crosswalk.CrosswalkException;
-import org.dspace.content.crosswalk.DisseminationCrosswalk;
-import org.dspace.content.crosswalk.ParameterizedDisseminationCrosswalk;
+import org.dspace.content.crosswalk.StreamDisseminationCrosswalk;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.DSpaceObjectService;
+import org.dspace.content.service.ItemService;
+import org.dspace.core.Constants;
import org.dspace.core.Context;
-import org.dspace.core.factory.CoreServiceFactory;
import org.dspace.handle.service.HandleService;
import org.dspace.identifier.DOI;
import org.dspace.services.ConfigurationService;
@@ -99,18 +101,6 @@ public class DataCiteConnector
* dependency injection.
*/
protected String METADATA_PATH;
- /**
- * Name of crosswalk to convert metadata into DataCite Metadata Scheme. Set
- * by spring dependency injection.
- */
- protected String CROSSWALK_NAME;
- /**
- * DisseminationCrosswalk to map local metadata into DataCite metadata.
- * The name of the crosswalk is set by spring dependency injection using
- * {@link #setDisseminationCrosswalkName(String) setDisseminationCrosswalkName} which
- * instantiates the crosswalk.
- */
- protected ParameterizedDisseminationCrosswalk xwalk;
protected ConfigurationService configurationService;
@@ -119,8 +109,12 @@ public class DataCiteConnector
@Autowired
protected HandleService handleService;
+ @Autowired
+ private ItemService itemService;
+
+ private Map disseminationCrosswalkByEntityType;
+
public DataCiteConnector() {
- this.xwalk = null;
this.USERNAME = null;
this.PASSWORD = null;
}
@@ -189,34 +183,6 @@ public void setConfigurationService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
- /**
- * Set the name of the dissemination crosswalk used to convert the metadata
- * into DataCite Metadata Schema. Used by spring dependency injection.
- *
- * @param CROSSWALK_NAME The name of the dissemination crosswalk to use. This
- * crosswalk must be configured in dspace.cfg.
- */
- @Autowired(required = true)
- public void setDisseminationCrosswalkName(String CROSSWALK_NAME) {
- this.CROSSWALK_NAME = CROSSWALK_NAME;
- }
-
- protected void prepareXwalk() {
- if (null != this.xwalk) {
- return;
- }
-
- this.xwalk = (ParameterizedDisseminationCrosswalk) CoreServiceFactory.getInstance().getPluginService()
- .getNamedPlugin(
- DisseminationCrosswalk.class,
- this.CROSSWALK_NAME);
-
- if (this.xwalk == null) {
- throw new RuntimeException("Can't find crosswalk '"
- + CROSSWALK_NAME + "'!");
- }
- }
-
protected String getUsername() {
if (null == this.USERNAME) {
this.USERNAME = this.configurationService.getProperty(CFG_USER);
@@ -350,64 +316,43 @@ public void deleteDOI(Context context, String doi)
@Override
public void reserveDOI(Context context, DSpaceObject dso, String doi)
throws DOIIdentifierException {
- this.prepareXwalk();
DSpaceObjectService dSpaceObjectService = ContentServiceFactory.getInstance()
.getDSpaceObjectService(dso);
- if (!this.xwalk.canDisseminate(dso)) {
- log.error("Crosswalk " + this.CROSSWALK_NAME
- + " cannot disseminate DSO with type " + dso.getType()
- + " and ID " + dso.getID() + ". Giving up reserving the DOI "
- + doi + ".");
- throw new DOIIdentifierException("Cannot disseminate "
- + dSpaceObjectService.getTypeText(dso) + "/" + dso.getID()
- + " using crosswalk " + this.CROSSWALK_NAME + ".",
- DOIIdentifierException.CONVERSION_ERROR);
- }
+ StreamDisseminationCrosswalk xwalk = getStreamDisseminationCrosswalkByDso(dso);
- // Set the transform's parameters.
- // XXX Should the actual list be configurable?
- Map parameters = new HashMap<>();
- if (configurationService.hasProperty(CFG_PREFIX)) {
- parameters.put("prefix",
- configurationService.getProperty(CFG_PREFIX));
- }
- if (configurationService.hasProperty(CFG_PUBLISHER)) {
- parameters.put("publisher",
- configurationService.getProperty(CFG_PUBLISHER));
- }
- if (configurationService.hasProperty(CFG_DATAMANAGER)) {
- parameters.put("datamanager",
- configurationService.getProperty(CFG_DATAMANAGER));
- }
- if (configurationService.hasProperty(CFG_HOSTINGINSTITUTION)) {
- parameters.put("hostinginstitution",
- configurationService.getProperty(CFG_HOSTINGINSTITUTION));
+ if (xwalk == null) {
+ log.error("No crosswalk found for DSO with type " + dso.getType()
+ + " and ID " + dso.getID() + ". Giving up reserving the DOI "
+ + doi + ".");
+ throw new DOIIdentifierException("Cannot disseminate "
+ + dSpaceObjectService.getTypeText(dso) + "/" + dso.getID() + ".",
+ DOIIdentifierException.CONVERSION_ERROR);
}
Element root = null;
try {
- root = xwalk.disseminateElement(context, dso, parameters);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ xwalk.disseminate(context, dso, baos);
+ SAXBuilder builder = new SAXBuilder();
+ Document document = builder.build(new ByteArrayInputStream(baos.toByteArray()));
+ root = document.getRootElement();
} catch (AuthorizeException ae) {
log.error("Caught an AuthorizeException while disseminating DSO "
+ "with type " + dso.getType() + " and ID " + dso.getID()
+ ". Giving up to reserve DOI " + doi + ".", ae);
throw new DOIIdentifierException("AuthorizeException occured while "
- + "converting " + dSpaceObjectService.getTypeText(dso) + "/" + dso
- .getID()
- + " using crosswalk " + this.CROSSWALK_NAME + ".", ae,
+ + "converting " + dSpaceObjectService.getTypeText(dso) + "/" + dso + ".", ae,
DOIIdentifierException.CONVERSION_ERROR);
} catch (CrosswalkException ce) {
log.error("Caught an CrosswalkException while reserving a DOI ("
+ doi + ") for DSO with type " + dso.getType() + " and ID "
+ dso.getID() + ". Won't reserve the doi.", ce);
throw new DOIIdentifierException("CrosswalkException occured while "
- + "converting " + dSpaceObjectService.getTypeText(dso) + "/" + dso
- .getID()
- + " using crosswalk " + this.CROSSWALK_NAME + ".", ce,
+ + "converting " + dSpaceObjectService.getTypeText(dso) + "/" + dso + ".", ce,
DOIIdentifierException.CONVERSION_ERROR);
- } catch (IOException | SQLException ex) {
+ } catch (IOException | SQLException | JDOMException ex) {
throw new RuntimeException(ex);
}
@@ -462,6 +407,21 @@ public void reserveDOI(Context context, DSpaceObject dso, String doi)
}
}
+ private StreamDisseminationCrosswalk getStreamDisseminationCrosswalkByDso(DSpaceObject dso) {
+
+ if (dso.getType() != Constants.ITEM) {
+ return null;
+ }
+
+ String entityType = itemService.getEntityType((Item) dso);
+ if (StringUtils.isBlank(entityType)) {
+ entityType = "Publication";
+ }
+
+ return disseminationCrosswalkByEntityType.get(entityType);
+
+ }
+
@Override
public void registerDOI(Context context, DSpaceObject dso, String doi)
throws DOIIdentifierException {
@@ -631,7 +591,7 @@ protected DataCiteResponse sendMetadataPostRequest(String doi, Element metadataR
Format format = Format.getCompactFormat();
format.setEncoding("UTF-8");
XMLOutputter xout = new XMLOutputter(format);
- return sendMetadataPostRequest(doi, xout.outputString(new Document(metadataRoot)));
+ return sendMetadataPostRequest(doi, xout.outputString(metadataRoot.getDocument()));
}
protected DataCiteResponse sendMetadataPostRequest(String doi, String metadata)
@@ -842,12 +802,21 @@ protected Element addDOI(String doi, Element root) {
}
Element identifier = new Element("identifier",
configurationService.getProperty(CFG_NAMESPACE,
- "http://datacite.org/schema/kernel-3"));
+ "http://datacite.org/schema/kernel-4"));
identifier.setAttribute("identifierType", "DOI");
identifier.addContent(doi.substring(DOI.SCHEME.length()));
return root.addContent(0, identifier);
}
+ public Map getDisseminationCrosswalkByEntityType() {
+ return disseminationCrosswalkByEntityType;
+ }
+
+ public void setDisseminationCrosswalkByEntityType(
+ Map disseminationCrosswalkByEntityType) {
+ this.disseminationCrosswalkByEntityType = disseminationCrosswalkByEntityType;
+ }
+
protected class DataCiteResponse {
private final int statusCode;
private final String content;
diff --git a/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java b/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java
index 22a141e4685b..00dd7d6e7c15 100644
--- a/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java
+++ b/dspace-api/src/main/java/org/dspace/identifier/service/IdentifierService.java
@@ -9,9 +9,11 @@
import java.sql.SQLException;
import java.util.List;
+import java.util.Map;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
+import org.dspace.content.logic.Filter;
import org.dspace.core.Context;
import org.dspace.identifier.Identifier;
import org.dspace.identifier.IdentifierException;
@@ -103,6 +105,52 @@ void reserve(Context context, DSpaceObject dso, String identifier)
*/
void register(Context context, DSpaceObject dso) throws AuthorizeException, SQLException, IdentifierException;
+ /**
+ *
+ * Register identifiers for a DSO, with a map of logical filters for each Identifier class to apply
+ * at the time of local registration.
+ *
+ * @param context The relevant DSpace Context.
+ * @param dso DSpace object to be registered
+ * @param typeFilters If a service supports a given Identifier implementation, apply the associated filter
+ * @throws AuthorizeException if authorization error
+ * @throws SQLException if database error
+ * @throws IdentifierException if identifier error
+ */
+ void register(Context context, DSpaceObject dso, Map, Filter> typeFilters)
+ throws AuthorizeException, SQLException, IdentifierException;
+
+ /**
+ *
+ * Register identifier(s) for the given DSO just with providers that support that Identifier class, and
+ * apply the given filter if that provider extends FilteredIdentifierProvider
+ *
+ * @param context The relevant DSpace Context.
+ * @param dso DSpace object to be registered
+ * @param type Type of identifier to register
+ * @param filter If a service supports a given Identifier implementation, apply this specific filter
+ * @throws AuthorizeException if authorization error
+ * @throws SQLException if database error
+ * @throws IdentifierException if identifier error
+ */
+ void register(Context context, DSpaceObject dso, Class extends Identifier> type, Filter filter)
+ throws AuthorizeException, SQLException, IdentifierException;
+
+ /**
+ *
+ * Register identifier(s) for the given DSO just with providers that support that Identifier class, and
+ * apply the given filter if that provider extends FilteredIdentifierProvider
+ *
+ * @param context The relevant DSpace Context.
+ * @param dso DSpace object to be registered
+ * @param type Type of identifier to register
+ * @throws AuthorizeException if authorization error
+ * @throws SQLException if database error
+ * @throws IdentifierException if identifier error
+ */
+ void register(Context context, DSpaceObject dso, Class extends Identifier> type)
+ throws AuthorizeException, SQLException, IdentifierException;
+
/**
* Used to Register a specific Identifier (for example a Handle, hdl:1234.5/6).
* The provider is responsible for detecting and processing the appropriate
diff --git a/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java b/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java
index 04a08a7781a2..7c6336ed3c7f 100644
--- a/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/iiif/IIIFApiQueryServiceImpl.java
@@ -23,8 +23,7 @@
/**
- * Queries the configured IIIF server for image dimensions. Used for
- * formats that cannot be easily read using ImageIO (jpeg 2000).
+ * Queries the configured IIIF image server via the Image API.
*
* @author Michael Spalti mspalti@willamette.edu
*/
diff --git a/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSImportMetadataSourceServiceImpl.java
index 8fbe4ef2cf57..da59472c45a6 100644
--- a/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSImportMetadataSourceServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/importer/external/ads/ADSImportMetadataSourceServiceImpl.java
@@ -273,6 +273,9 @@ public Integer count(String query, String token) {
uriBuilder.addParameter("fl", this.resultFieldList);
String resp = liveImportClient.executeHttpGetRequest(timeout, uriBuilder.toString(), params);
+ if (StringUtils.isEmpty(resp)) {
+ return 0;
+ }
JsonNode jsonNode = convertStringJsonToJsonNode(resp);
return jsonNode.at("/response/numFound").asInt();
} catch (URISyntaxException e) {
@@ -296,6 +299,9 @@ public List search(String query, Integer start, Integer count, Str
uriBuilder.addParameter("fl", this.resultFieldList);
String resp = liveImportClient.executeHttpGetRequest(timeout, uriBuilder.toString(), params);
+ if (StringUtils.isEmpty(resp)) {
+ return adsResults;
+ }
JsonNode jsonNode = convertStringJsonToJsonNode(resp);
JsonNode docs = jsonNode.at("/response/docs");
diff --git a/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java
index 445dfedebdc6..0014088c8650 100644
--- a/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/importer/external/bibtex/service/BibtexImportMetadataSourceServiceImpl.java
@@ -105,10 +105,10 @@ private BibTeXDatabase parseBibTex(InputStream inputStream) throws IOException,
/**
- * Retrieve the MetadataFieldMapping containing the mapping between RecordType
+ * Set the MetadataFieldMapping containing the mapping between RecordType
* (in this case PlainMetadataSourceDto.class) and Metadata
*
- * @return The configured MetadataFieldMapping
+ * @param metadataFieldMap The configured MetadataFieldMapping
*/
@Override
@SuppressWarnings("unchecked")
diff --git a/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java
index 5eff46c790e4..53230d960831 100644
--- a/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/importer/external/cinii/CiniiImportMetadataSourceServiceImpl.java
@@ -289,6 +289,9 @@ protected List search(String id, String appId)
URIBuilder uriBuilder = new URIBuilder(this.url + id + ".rdf?appid=" + appId);
Map> params = new HashMap>();
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
+ if (StringUtils.isBlank(response)) {
+ return records;
+ }
List elements = splitToRecords(response);
for (Element record : elements) {
records.add(transformSourceRecords(record));
@@ -416,6 +419,9 @@ private Integer countCiniiElement(String appId, Integer maxResult, String author
Map> params = new HashMap>();
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
+ if (StringUtils.isEmpty(response)) {
+ return 0;
+ }
SAXBuilder saxBuilder = new SAXBuilder();
Document document = saxBuilder.build(new StringReader(response));
diff --git a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefImportMetadataSourceServiceImpl.java
index 7dde330b27ec..5c4c49deaec9 100644
--- a/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefImportMetadataSourceServiceImpl.java
+++ b/dspace-api/src/main/java/org/dspace/importer/external/crossref/CrossRefImportMetadataSourceServiceImpl.java
@@ -158,6 +158,9 @@ public List call() throws Exception {
}
Map> params = new HashMap>();
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
+ if (StringUtils.isEmpty(response)) {
+ return results;
+ }
JsonNode jsonNode = convertStringJsonToJsonNode(response);
Iterator nodes = jsonNode.at("/message/items").iterator();
while (nodes.hasNext()) {
@@ -194,6 +197,9 @@ public List call() throws Exception {
URIBuilder uriBuilder = new URIBuilder(url + "/" + ID);
Map> params = new HashMap>();
String responseString = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
+ if (StringUtils.isEmpty(responseString)) {
+ return results;
+ }
JsonNode jsonNode = convertStringJsonToJsonNode(responseString);
JsonNode messageNode = jsonNode.at("/message");
results.add(transformSourceRecords(messageNode.toString()));
@@ -246,6 +252,9 @@ public List call() throws Exception {
}
Map> params = new HashMap>();
String resp = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
+ if (StringUtils.isEmpty(resp)) {
+ return results;
+ }
JsonNode jsonNode = convertStringJsonToJsonNode(resp);
Iterator nodes = jsonNode.at("/message/items").iterator();
while (nodes.hasNext()) {
@@ -284,6 +293,9 @@ public Integer call() throws Exception {
uriBuilder.addParameter("query", query.getParameterAsClass("query", String.class));
Map> params = new HashMap>();
String responseString = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
+ if (StringUtils.isEmpty(responseString)) {
+ return 0;
+ }
JsonNode jsonNode = convertStringJsonToJsonNode(responseString);
return jsonNode.at("/message/total-results").asInt();
}
diff --git a/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteFieldMapping.java b/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteFieldMapping.java
new file mode 100644
index 000000000000..f8540307b916
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteFieldMapping.java
@@ -0,0 +1,38 @@
+/**
+ * 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.datacite;
+
+import java.util.Map;
+import javax.annotation.Resource;
+
+import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping;
+
+/**
+ * An implementation of {@link AbstractMetadataFieldMapping}
+ * Responsible for defining the mapping of the datacite metadatum fields on the DSpace metadatum fields
+ *
+ * @author Pasquale Cavallo (pasquale.cavallo at 4science dot it)
+ * @author Florian Gantner (florian.gantner@uni-bamberg.de)
+ */
+public class DataCiteFieldMapping extends AbstractMetadataFieldMapping {
+
+ /**
+ * Defines which metadatum is mapped on which metadatum. Note that while the key must be unique it
+ * only matters here for postprocessing of the value. The mapped MetadatumContributor has full control over
+ * what metadatafield is generated.
+ *
+ * @param metadataFieldMap The map containing the link between retrieve metadata and metadata that will be set to
+ * the item.
+ */
+ @Override
+ @Resource(name = "dataciteMetadataFieldMap")
+ public void setMetadataFieldMap(Map metadataFieldMap) {
+ super.setMetadataFieldMap(metadataFieldMap);
+ }
+
+}
diff --git a/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteImportMetadataSourceServiceImpl.java b/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteImportMetadataSourceServiceImpl.java
new file mode 100644
index 000000000000..a11f2bc2471d
--- /dev/null
+++ b/dspace-api/src/main/java/org/dspace/importer/external/datacite/DataCiteImportMetadataSourceServiceImpl.java
@@ -0,0 +1,168 @@
+/**
+ * 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.datacite;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.el.MethodNotFoundException;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.dspace.content.Item;
+import org.dspace.importer.external.datamodel.ImportRecord;
+import org.dspace.importer.external.datamodel.Query;
+import org.dspace.importer.external.exception.MetadataSourceException;
+import org.dspace.importer.external.liveimportclient.service.LiveImportClient;
+import org.dspace.importer.external.service.AbstractImportMetadataSourceService;
+import org.dspace.importer.external.service.DoiCheck;
+import org.dspace.importer.external.service.components.QuerySource;
+import org.dspace.services.ConfigurationService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Implements a data source for querying Datacite
+ * Mainly copied from CrossRefImportMetadataSourceServiceImpl.
+ *
+ * optional Affiliation informations are not part of the API request.
+ * https://support.datacite.org/docs/can-i-see-more-detailed-affiliation-information-in-the-rest-api
+ *
+ * @author Pasquale Cavallo (pasquale.cavallo at 4science dot it)
+ * @author Florian Gantner (florian.gantner@uni-bamberg.de)
+ *
+ */
+public class DataCiteImportMetadataSourceServiceImpl
+ extends AbstractImportMetadataSourceService implements QuerySource {
+ private final static Logger log = LogManager.getLogger();
+
+ @Autowired
+ private LiveImportClient liveImportClient;
+
+ @Autowired
+ private ConfigurationService configurationService;
+
+ @Override
+ public String getImportSource() {
+ return "datacite";
+ }
+
+ @Override
+ public void init() throws Exception {
+ }
+
+ @Override
+ public ImportRecord getRecord(String recordId) throws MetadataSourceException {
+ Collection records = getRecords(recordId, 0, 1);
+ if (records.size() == 0) {
+ return null;
+ }
+ return records.stream().findFirst().get();
+ }
+
+ @Override
+ public int getRecordsCount(String query) throws MetadataSourceException {
+ Collection