diff --git a/docker-compose.yml b/docker-compose.yml index 38007908c6..14f47ebdb6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -121,6 +121,8 @@ services: cp -r /opt/solr/server/solr/configsets/search/* search precreate-core statistics /opt/solr/server/solr/configsets/statistics cp -r /opt/solr/server/solr/configsets/statistics/* statistics + precreate-core qaevent /opt/solr/server/solr/configsets/qaevent + cp -r /opt/solr/server/solr/configsets/qaevent/* qaevent exec solr -f volumes: assetstore: 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 e09e4725ca..f6144961c6 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -77,7 +77,7 @@ import org.dspace.orcid.service.OrcidQueueService; import org.dspace.orcid.service.OrcidSynchronizationService; import org.dspace.orcid.service.OrcidTokenService; import org.dspace.profile.service.ResearcherProfileService; -import org.dspace.qaevent.dao.QAEventsDao; +import org.dspace.qaevent.dao.QAEventsDAO; import org.dspace.services.ConfigurationService; import org.dspace.versioning.service.VersioningService; import org.dspace.workflow.WorkflowItemService; @@ -172,7 +172,7 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It protected SubscribeService subscribeService; @Autowired - private QAEventsDao qaEventsDao; + private QAEventsDAO qaEventsDao; protected ItemServiceImpl() { super(); diff --git a/dspace-api/src/main/java/org/dspace/content/QAEvent.java b/dspace-api/src/main/java/org/dspace/content/QAEvent.java index 1c39c2a21e..cf6c06446c 100644 --- a/dspace-api/src/main/java/org/dspace/content/QAEvent.java +++ b/dspace-api/src/main/java/org/dspace/content/QAEvent.java @@ -37,9 +37,17 @@ public class QAEvent { private String source; private String eventId; - + /** + * contains the targeted dspace object, + * ie: oai:www.openstarts.units.it:123456789/1120 contains the handle + * of the DSpace pbject in its final part 123456789/1120 + * */ private String originalId; + /** + * evaluated with the targeted dspace object id + * + * */ private String target; private String related; diff --git a/dspace-api/src/main/java/org/dspace/eperson/EPersonServiceImpl.java b/dspace-api/src/main/java/org/dspace/eperson/EPersonServiceImpl.java index 0a8f6d6f3d..b9fde450c2 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/EPersonServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/eperson/EPersonServiceImpl.java @@ -48,7 +48,7 @@ import org.dspace.eperson.service.GroupService; import org.dspace.eperson.service.SubscribeService; import org.dspace.event.Event; import org.dspace.orcid.service.OrcidTokenService; -import org.dspace.qaevent.dao.QAEventsDao; +import org.dspace.qaevent.dao.QAEventsDAO; import org.dspace.services.ConfigurationService; import org.dspace.util.UUIDUtils; import org.dspace.versioning.Version; @@ -109,7 +109,7 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl impleme @Autowired protected OrcidTokenService orcidTokenService; @Autowired - protected QAEventsDao qaEventsDao; + protected QAEventsDAO qaEventsDao; protected EPersonServiceImpl() { super(); diff --git a/dspace-api/src/main/java/org/dspace/external/OpenAIRERestConnector.java b/dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java similarity index 92% rename from dspace-api/src/main/java/org/dspace/external/OpenAIRERestConnector.java rename to dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java index b0aa4aba13..c96fad1de0 100644 --- a/dspace-api/src/main/java/org/dspace/external/OpenAIRERestConnector.java +++ b/dspace-api/src/main/java/org/dspace/external/OpenaireRestConnector.java @@ -40,20 +40,20 @@ import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; /** - * based on OrcidRestConnector it's a rest connector for OpenAIRE API providing + * based on OrcidRestConnector it's a rest connector for Openaire API providing * ways to perform searches and token grabbing * * @author paulo-graca * */ -public class OpenAIRERestConnector { +public class OpenaireRestConnector { /** * log4j logger */ - private static Logger log = org.apache.logging.log4j.LogManager.getLogger(OpenAIRERestConnector.class); + private static Logger log = org.apache.logging.log4j.LogManager.getLogger(OpenaireRestConnector.class); /** - * OpenAIRE API Url + * Openaire API Url * and can be configured with: openaire.api.url */ private String url = "https://api.openaire.eu"; @@ -65,30 +65,30 @@ public class OpenAIRERestConnector { boolean tokenEnabled = false; /** - * OpenAIRE Authorization and Authentication Token Service URL + * Openaire Authorization and Authentication Token Service URL * and can be configured with: openaire.token.url */ private String tokenServiceUrl; /** - * OpenAIRE clientId + * Openaire clientId * and can be configured with: openaire.token.clientId */ private String clientId; /** - * OpenAIRERest access token + * OpenaireRest access token */ - private OpenAIRERestToken accessToken; + private OpenaireRestToken accessToken; /** - * OpenAIRE clientSecret + * Openaire clientSecret * and can be configured with: openaire.token.clientSecret */ private String clientSecret; - public OpenAIRERestConnector(String url) { + public OpenaireRestConnector(String url) { this.url = url; } @@ -99,7 +99,7 @@ public class OpenAIRERestConnector { * * @throws IOException */ - public OpenAIRERestToken grabNewAccessToken() throws IOException { + public OpenaireRestToken grabNewAccessToken() throws IOException { if (StringUtils.isBlank(tokenServiceUrl) || StringUtils.isBlank(clientId) || StringUtils.isBlank(clientSecret)) { @@ -145,13 +145,13 @@ public class OpenAIRERestConnector { throw new IOException("Unable to grab the access token using provided service url, client id and secret"); } - return new OpenAIRERestToken(responseObject.get("access_token").toString(), + return new OpenaireRestToken(responseObject.get("access_token").toString(), Long.valueOf(responseObject.get("expires_in").toString())); } /** - * Perform a GET request to the OpenAIRE API + * Perform a GET request to the Openaire API * * @param file * @param accessToken @@ -218,12 +218,12 @@ public class OpenAIRERestConnector { } /** - * Perform an OpenAIRE Project Search By Keywords + * Perform an Openaire Project Search By Keywords * * @param page * @param size * @param keywords - * @return OpenAIRE Response + * @return Openaire Response */ public Response searchProjectByKeywords(int page, int size, String... keywords) { String path = "search/projects?keywords=" + String.join("+", keywords); @@ -231,13 +231,13 @@ public class OpenAIRERestConnector { } /** - * Perform an OpenAIRE Project Search By ID and by Funder + * Perform an Openaire Project Search By ID and by Funder * * @param projectID * @param projectFunder * @param page * @param size - * @return OpenAIRE Response + * @return Openaire Response */ public Response searchProjectByIDAndFunder(String projectID, String projectFunder, int page, int size) { String path = "search/projects?grantID=" + projectID + "&funder=" + projectFunder; @@ -245,12 +245,12 @@ public class OpenAIRERestConnector { } /** - * Perform an OpenAIRE Search request + * Perform an Openaire Search request * * @param path * @param page * @param size - * @return OpenAIRE Response + * @return Openaire Response */ public Response search(String path, int page, int size) { String[] queryStringPagination = { "page=" + page, "size=" + size }; diff --git a/dspace-api/src/main/java/org/dspace/external/OpenAIRERestToken.java b/dspace-api/src/main/java/org/dspace/external/OpenaireRestToken.java similarity index 89% rename from dspace-api/src/main/java/org/dspace/external/OpenAIRERestToken.java rename to dspace-api/src/main/java/org/dspace/external/OpenaireRestToken.java index 203f09b3c6..f5dc2b27f8 100644 --- a/dspace-api/src/main/java/org/dspace/external/OpenAIRERestToken.java +++ b/dspace-api/src/main/java/org/dspace/external/OpenaireRestToken.java @@ -8,13 +8,13 @@ package org.dspace.external; /** - * OpenAIRE rest API token to be used when grabbing an accessToken.
+ * Openaire rest API token to be used when grabbing an accessToken.
* Based on https://develop.openaire.eu/basic.html * * @author paulo-graca * */ -public class OpenAIRERestToken { +public class OpenaireRestToken { /** * Stored access token @@ -32,7 +32,7 @@ public class OpenAIRERestToken { * @param accessToken * @param expiresIn */ - public OpenAIRERestToken(String accessToken, Long expiresIn) { + public OpenaireRestToken(String accessToken, Long expiresIn) { this.accessToken = accessToken; this.setExpirationDate(expiresIn); } diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/OpenAIREFundingDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/OpenaireFundingDataProvider.java similarity index 94% rename from dspace-api/src/main/java/org/dspace/external/provider/impl/OpenAIREFundingDataProvider.java rename to dspace-api/src/main/java/org/dspace/external/provider/impl/OpenaireFundingDataProvider.java index 8ca5b7c0ea..62cef508c5 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/OpenAIREFundingDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/OpenaireFundingDataProvider.java @@ -31,7 +31,7 @@ import eu.openaire.oaf.model.base.Project; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.content.dto.MetadataValueDTO; -import org.dspace.external.OpenAIRERestConnector; +import org.dspace.external.OpenaireRestConnector; import org.dspace.external.model.ExternalDataObject; import org.dspace.external.provider.AbstractExternalDataProvider; import org.dspace.importer.external.metadatamapping.MetadataFieldConfig; @@ -39,13 +39,13 @@ import org.springframework.beans.factory.annotation.Autowired; /** * This class is the implementation of the ExternalDataProvider interface that - * will deal with the OpenAIRE External Data lookup + * will deal with the Openaire External Data lookup * * @author paulo-graca */ -public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { +public class OpenaireFundingDataProvider extends AbstractExternalDataProvider { - private static Logger log = org.apache.logging.log4j.LogManager.getLogger(OpenAIREFundingDataProvider.class); + private static Logger log = org.apache.logging.log4j.LogManager.getLogger(OpenaireFundingDataProvider.class); /** * GrantAgreement prefix @@ -75,7 +75,7 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { /** * Connector to handle token and requests */ - protected OpenAIRERestConnector connector; + protected OpenaireRestConnector connector; protected Map metadataFields; @@ -93,7 +93,7 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { // characters that must be escaped for the <:entry-id> String decodedId = new String(Base64.getDecoder().decode(id)); if (!isValidProjectURI(decodedId)) { - log.error("Invalid ID for OpenAIREFunding - " + id); + log.error("Invalid ID for OpenaireFunding - " + id); return Optional.empty(); } Response response = searchByProjectURI(decodedId); @@ -101,7 +101,7 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { try { if (response.getHeader() != null && Integer.parseInt(response.getHeader().getTotal()) > 0) { Project project = response.getResults().getResult().get(0).getMetadata().getEntity().getProject(); - ExternalDataObject externalDataObject = new OpenAIREFundingDataProvider + ExternalDataObject externalDataObject = new OpenaireFundingDataProvider .ExternalDataObjectBuilder(project) .setId(generateProjectURI(project)) .setSource(sourceIdentifier) @@ -123,7 +123,7 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { limit = LIMIT_DEFAULT; } - // OpenAIRE uses pages and first page starts with 1 + // Openaire uses pages and first page starts with 1 int page = (start / limit) + 1; // escaping query @@ -148,7 +148,7 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { if (projects.size() > 0) { return projects.stream() - .map(project -> new OpenAIREFundingDataProvider + .map(project -> new OpenaireFundingDataProvider .ExternalDataObjectBuilder(project) .setId(generateProjectURI(project)) .setSource(sourceIdentifier) @@ -176,24 +176,24 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { * Generic setter for the sourceIdentifier * * @param sourceIdentifier The sourceIdentifier to be set on this - * OpenAIREFunderDataProvider + * OpenaireFunderDataProvider */ @Autowired(required = true) public void setSourceIdentifier(String sourceIdentifier) { this.sourceIdentifier = sourceIdentifier; } - public OpenAIRERestConnector getConnector() { + public OpenaireRestConnector getConnector() { return connector; } /** - * Generic setter for OpenAIRERestConnector + * Generic setter for OpenaireRestConnector * * @param connector */ @Autowired(required = true) - public void setConnector(OpenAIRERestConnector connector) { + public void setConnector(OpenaireRestConnector connector) { this.connector = connector; } @@ -219,7 +219,7 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { } /** - * This method returns an URI based on OpenAIRE 3.0 guidelines + * This method returns an URI based on Openaire 3.0 guidelines * https://guidelines.openaire.eu/en/latest/literature/field_projectid.html that * can be used as an ID if is there any missing part, that part it will be * replaced by the character '+' @@ -281,7 +281,7 @@ public class OpenAIREFundingDataProvider extends AbstractExternalDataProvider { } /** - * OpenAIRE Funding External Data Builder Class + * Openaire Funding External Data Builder Class * * @author pgraca */ diff --git a/dspace-api/src/main/java/org/dspace/qaevent/QAEventsDeleteCascadeConsumer.java b/dspace-api/src/main/java/org/dspace/qaevent/QAEventsDeleteCascadeConsumer.java index 68976430e6..6460c360ec 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/QAEventsDeleteCascadeConsumer.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/QAEventsDeleteCascadeConsumer.java @@ -16,7 +16,7 @@ import org.dspace.qaevent.service.QAEventService; import org.dspace.utils.DSpace; /** - * Consumer to delete qaevents once the target item is deleted + * Consumer to delete qaevents from solr due to the target item deletion * * @author Andrea Bollini (andrea.bollini at 4science.it) * diff --git a/dspace-api/src/main/java/org/dspace/qaevent/QASource.java b/dspace-api/src/main/java/org/dspace/qaevent/QASource.java index afd598cfde..852dd0b100 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/QASource.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/QASource.java @@ -11,7 +11,7 @@ import java.util.Date; import java.util.UUID; /** - * This model class represent the source/provider of the QA events (as OpenAIRE). + * This model class represent the source/provider of the QA events (as Openaire). * * @author Luca Giamminonni (luca.giamminonni at 4Science) * diff --git a/dspace-api/src/main/java/org/dspace/qaevent/dao/QAEventsDao.java b/dspace-api/src/main/java/org/dspace/qaevent/dao/QAEventsDAO.java similarity index 98% rename from dspace-api/src/main/java/org/dspace/qaevent/dao/QAEventsDao.java rename to dspace-api/src/main/java/org/dspace/qaevent/dao/QAEventsDAO.java index 9de2d12460..98c38ca3f5 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/dao/QAEventsDao.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/dao/QAEventsDAO.java @@ -22,7 +22,7 @@ import org.dspace.eperson.EPerson; * @author Andrea Bollini (andrea.bollini at 4science.it) * */ -public interface QAEventsDao extends GenericDAO { +public interface QAEventsDAO extends GenericDAO { /** * Returns all the stored QAEventProcessed entities. diff --git a/dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDaoImpl.java b/dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDAOImpl.java similarity index 89% rename from dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDaoImpl.java rename to dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDAOImpl.java index 3263ae9de9..ac9b96045e 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDaoImpl.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/dao/impl/QAEventsDAOImpl.java @@ -17,16 +17,16 @@ import org.dspace.content.QAEventProcessed; import org.dspace.core.AbstractHibernateDAO; import org.dspace.core.Context; import org.dspace.eperson.EPerson; -import org.dspace.qaevent.dao.QAEventsDao; +import org.dspace.qaevent.dao.QAEventsDAO; /** - * Implementation of {@link QAEventsDao} that store processed events using an + * Implementation of {@link QAEventsDAO} that store processed events using an * SQL DBMS. * * @author Andrea Bollini (andrea.bollini at 4science.it) * */ -public class QAEventsDaoImpl extends AbstractHibernateDAO implements QAEventsDao { +public class QAEventsDAOImpl extends AbstractHibernateDAO implements QAEventsDAO { @Override public List findAll(Context context) throws SQLException { @@ -60,7 +60,7 @@ public class QAEventsDaoImpl extends AbstractHibernateDAO impl public List searchByEventId(Context context, String eventId, Integer start, Integer size) throws SQLException { Query query = createQuery(context, - "SELECT * " + "FROM QAEventProcessed qaevent WHERE qaevent.qaevent_id = :event_id "); + "SELECT * FROM QAEventProcessed qaevent WHERE qaevent.qaevent_id = :event_id "); query.setFirstResult(start); query.setMaxResults(size); query.setParameter("event_id", eventId); diff --git a/dspace-api/src/main/java/org/dspace/qaevent/script/OpenaireEventsImport.java b/dspace-api/src/main/java/org/dspace/qaevent/script/OpenaireEventsImport.java index e45dc3e159..9087606aa6 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/script/OpenaireEventsImport.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/script/OpenaireEventsImport.java @@ -32,7 +32,7 @@ import org.dspace.content.QAEvent; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.factory.EPersonServiceFactory; -import org.dspace.qaevent.service.BrokerClientFactory; +import org.dspace.qaevent.service.OpenaireClientFactory; import org.dspace.qaevent.service.QAEventService; import org.dspace.scripts.DSpaceRunnable; import org.dspace.services.ConfigurationService; @@ -42,7 +42,9 @@ import org.dspace.utils.DSpace; /** * Implementation of {@link DSpaceRunnable} to perfom a QAEvents import from a * json file. The JSON file contains an array of JSON Events, where each event - * has the following structure + * has the following structure. The message attribute follows the structure + * documented at + * @see see * *
* {
@@ -103,7 +105,7 @@ public class OpenaireEventsImport qaEventService = new DSpace().getSingletonService(QAEventService.class); configurationService = DSpaceServicesFactory.getInstance().getConfigurationService(); - brokerClient = BrokerClientFactory.getInstance().getBrokerClient(); + brokerClient = OpenaireClientFactory.getInstance().getBrokerClient(); topicsToImport = configurationService.getArrayProperty("qaevents.openaire.import.topic"); openaireBrokerURL = getOpenaireBrokerUri(); diff --git a/dspace-api/src/main/java/org/dspace/qaevent/script/OpenaireEventsImportScriptConfiguration.java b/dspace-api/src/main/java/org/dspace/qaevent/script/OpenaireEventsImportScriptConfiguration.java index 14737de635..60001e7350 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/script/OpenaireEventsImportScriptConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/script/OpenaireEventsImportScriptConfiguration.java @@ -54,12 +54,12 @@ public class OpenaireEventsImportScriptConfiguration findAllTopics(Context context, long offset, long count, String orderField, boolean ascending); + /** * Find all the event's topics related to the given source. * @@ -33,7 +41,8 @@ public interface QAEventService { * @param count the page size * @return the topics list */ - public List findAllTopicsBySource(Context context, String source, long offset, int count); + public List findAllTopicsBySource(Context context, String source, long offset, long count, + String orderField, boolean ascending); /** * Find a specific topic by its name, source and optionally a target. @@ -186,11 +195,13 @@ public interface QAEventService { * @param source (not null) the source to search for * @param target the item referring to * @param offset the offset to apply - * @param pageSize the page size + * @param count result count + * @param orderField field name for sorting + * @param ascending activate ascending sort * @return the topics list */ public List findAllTopicsBySourceAndTarget(Context context, String source, UUID target, long offset, - int pageSize); + long count, String orderField, boolean ascending); /** * Count all the event's topics related to the given source referring to a specific item diff --git a/dspace-api/src/main/java/org/dspace/qaevent/service/dto/OpenaireMessageDTO.java b/dspace-api/src/main/java/org/dspace/qaevent/service/dto/OpenaireMessageDTO.java index 0be5c3c39f..821f11f869 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/service/dto/OpenaireMessageDTO.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/service/dto/OpenaireMessageDTO.java @@ -12,7 +12,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** * Implementation of {@link QAMessageDTO} that model message coming from OPENAIRE. - * + * @see see * @author Luca Giamminonni (luca.giamminonni at 4science.it) * */ diff --git a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/BrokerClientFactoryImpl.java b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/OpenaireClientFactoryImpl.java similarity index 78% rename from dspace-api/src/main/java/org/dspace/qaevent/service/impl/BrokerClientFactoryImpl.java rename to dspace-api/src/main/java/org/dspace/qaevent/service/impl/OpenaireClientFactoryImpl.java index 8d3f2cdaac..5839f5e877 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/BrokerClientFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/OpenaireClientFactoryImpl.java @@ -8,17 +8,17 @@ package org.dspace.qaevent.service.impl; import eu.dnetlib.broker.BrokerClient; -import org.dspace.qaevent.service.BrokerClientFactory; +import org.dspace.qaevent.service.OpenaireClientFactory; import org.springframework.beans.factory.annotation.Autowired; /** - * Implementation of {@link BrokerClientFactory} that returns the instance of + * Implementation of {@link OpenaireClientFactory} that returns the instance of * {@link BrokerClient} managed by the Spring context. * * @author Luca Giamminonni (luca.giamminonni at 4science.it) * */ -public class BrokerClientFactoryImpl implements BrokerClientFactory { +public class OpenaireClientFactoryImpl implements OpenaireClientFactory { @Autowired private BrokerClient brokerClient; diff --git a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventServiceImpl.java b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventServiceImpl.java index d24a20ffb1..c6cf5653c2 100644 --- a/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/qaevent/service/impl/QAEventServiceImpl.java @@ -40,6 +40,7 @@ import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.FacetParams; import org.dspace.content.Item; import org.dspace.content.QAEvent; import org.dspace.content.service.ItemService; @@ -50,8 +51,8 @@ import org.dspace.qaevent.AutomaticProcessingAction; import org.dspace.qaevent.QAEventAutomaticProcessingEvaluation; import org.dspace.qaevent.QASource; import org.dspace.qaevent.QATopic; -import org.dspace.qaevent.dao.QAEventsDao; -import org.dspace.qaevent.dao.impl.QAEventsDaoImpl; +import org.dspace.qaevent.dao.QAEventsDAO; +import org.dspace.qaevent.dao.impl.QAEventsDAOImpl; import org.dspace.qaevent.service.QAEventActionService; import org.dspace.qaevent.service.QAEventSecurityService; import org.dspace.qaevent.service.QAEventService; @@ -60,11 +61,12 @@ import org.dspace.services.factory.DSpaceServicesFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; + /** * Implementation of {@link QAEventService} that use Solr to store events. When * the user performs an action on the event (such as accepting the suggestion or * rejecting it) then the event is removed from solr and saved in the database - * (see {@link QAEventsDao}) so that it is no longer proposed. + * (see {@link QAEventsDAO}) so that it is no longer proposed. * * @author Andrea Bollini (andrea.bollini at 4science.it) * @@ -86,7 +88,7 @@ public class QAEventServiceImpl implements QAEventService { private HandleService handleService; @Autowired - private QAEventsDaoImpl qaEventsDao; + private QAEventsDAOImpl qaEventsDao; @Autowired(required = false) @Qualifier("qaAutomaticProcessingMap") @@ -240,19 +242,29 @@ public class QAEventServiceImpl implements QAEventService { } @Override - public List findAllTopicsBySource(Context context, String source, long offset, int count) { - return findAllTopicsBySourceAndTarget(context, source, null, offset, count); + public List findAllTopics(Context context, long offset, long count, String orderField, boolean ascending) { + return findAllTopicsBySource(context, null, offset, count, orderField, ascending); + } + + @Override + public List findAllTopicsBySource(Context context, String source, long offset, + long count, String orderField, boolean ascending) { + return findAllTopicsBySourceAndTarget(context, source, null, offset, count, orderField, ascending); } @Override public List findAllTopicsBySourceAndTarget(Context context, String source, UUID target, long offset, - int count) { + long count, String orderField, boolean ascending) { if (isNotSupportedSource(source) || !qaSecurityService.canSeeSource(context, context.getCurrentUser(), source)) { return List.of(); } SolrQuery solrQuery = new SolrQuery(); solrQuery.setRows(0); + if (orderField != null) { + solrQuery.setSort(orderField, ascending ? ORDER.asc : ORDER.desc); + solrQuery.setFacetSort(FacetParams.FACET_SORT_INDEX); + } Optional securityQuery = qaSecurityService.generateQAEventFilterQuery(context, context.getCurrentUser(), source); solrQuery.setQuery(securityQuery.orElse("*:*")); diff --git a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V8.0_2023.08.07__qaevent_processed.sql b/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V8.0_2023.08.07__qaevent_processed.sql deleted file mode 100644 index 5c3f0fac73..0000000000 --- a/dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V8.0_2023.08.07__qaevent_processed.sql +++ /dev/null @@ -1,19 +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/ --- - -CREATE TABLE qaevent_processed ( - qaevent_id VARCHAR(255) NOT NULL, - qaevent_timestamp TIMESTAMP NULL, - eperson_uuid UUID NULL, - item_uuid UUID NULL, - CONSTRAINT qaevent_pk PRIMARY KEY (qaevent_id), - CONSTRAINT eperson_uuid_fkey FOREIGN KEY (eperson_uuid) REFERENCES eperson (uuid), - CONSTRAINT item_uuid_fkey FOREIGN KEY (item_uuid) REFERENCES item (uuid) -); - -CREATE INDEX item_uuid_idx ON qaevent_processed(item_uuid); diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/external-openaire.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/external-openaire.xml index f1e6c30d13..8a5277ab2d 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/external-openaire.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/external-openaire.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/util/spring-util.xsd" default-lazy-init="true"> - + @@ -15,10 +15,10 @@ - - + + diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/item-filters.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/item-filters.xml index 836d4f0896..8bae32eaef 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/item-filters.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/item-filters.xml @@ -286,7 +286,7 @@ - @@ -329,7 +329,7 @@ - diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/scripts.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/scripts.xml index b80330564f..a197b2910b 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/scripts.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/scripts.xml @@ -66,7 +66,7 @@ - + diff --git a/dspace-api/src/test/java/org/dspace/builder/QAEventBuilder.java b/dspace-api/src/test/java/org/dspace/builder/QAEventBuilder.java index 154bf737d9..823080516d 100644 --- a/dspace-api/src/test/java/org/dspace/builder/QAEventBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/QAEventBuilder.java @@ -25,9 +25,21 @@ public class QAEventBuilder extends AbstractBuilder { private Item item; private QAEvent target; private String source = QAEvent.OPENAIRE_SOURCE; + /** + * the title of the DSpace object + * */ private String title; + /** + * the name of the Quality Assurance Event Topic + * */ private String topic; + /** + * thr original QA Event imported + * */ private String message; + /** + * uuid of the targeted DSpace object + * */ private String relatedItem; private double trust = 0.5; private Date lastUpdate = new Date(); diff --git a/dspace-api/src/test/java/org/dspace/content/CollectionTest.java b/dspace-api/src/test/java/org/dspace/content/CollectionTest.java index 13d037abf8..a177571ffa 100644 --- a/dspace-api/src/test/java/org/dspace/content/CollectionTest.java +++ b/dspace-api/src/test/java/org/dspace/content/CollectionTest.java @@ -1200,4 +1200,71 @@ public class CollectionTest extends AbstractDSpaceObjectTest { equalTo(owningCommunity)); } + /** + * Test of retrieveCollectionWithSubmitByEntityType method getting the closest + * collection of non-item type starting from an item + */ + @Test + public void testRetrieveCollectionWithSubmitByEntityType() throws SQLException, AuthorizeException { + context.setDispatcher("default"); + context.turnOffAuthorisationSystem(); + Community com = communityService.create(null, context); + Group submitters = groupService.create(context); + Collection collection = collectionService.create(context, com); + collectionService.addMetadata(context, collection, "dspace", "entity", "type", + null, "Publication"); + com.addCollection(collection); + WorkspaceItem workspaceItem = workspaceItemService.create(context, collection, false); + Item item = installItemService.installItem(context, workspaceItem); + EPerson epersonA = ePersonService.create(context); + Collection collectionPerson = collectionService.create(context, com); + collectionService.addMetadata(context, collectionPerson, "dspace", "entity", "type", + null, "Person"); + collectionPerson.setSubmitters(submitters); + groupService.addMember(context, submitters, epersonA); + context.setCurrentUser(epersonA); + context.commit(); + context.restoreAuthSystemState(); + Collection resultCollection = collectionService.retrieveCollectionWithSubmitByEntityType + (context, item, "Person"); + + assertThat("testRetrieveCollectionWithSubmitByEntityType 0", resultCollection, notNullValue()); + assertThat("testRetrieveCollectionWithSubmitByEntityType 1", resultCollection, equalTo(collectionPerson)); + + context.setDispatcher("exclude-discovery"); + } + + /** + * Test of rretrieveCollectionWithSubmitByCommunityAndEntityType method getting the closest + * collection of non-community type starting from an community + */ + @Test + public void testRetrieveCollectionWithSubmitByCommunityAndEntityType() throws SQLException, AuthorizeException { + context.setDispatcher("default"); + context.turnOffAuthorisationSystem(); + Community com = communityService.create(null, context); + Group submitters = groupService.create(context); + Collection collection = collectionService.create(context, com); + collectionService.addMetadata(context, collection, "dspace", "entity", "type", + null, "Publication"); + com.addCollection(collection); + WorkspaceItem workspaceItem = workspaceItemService.create(context, collection, false); + Item item = installItemService.installItem(context, workspaceItem); + EPerson epersonA = ePersonService.create(context); + Collection collectionPerson = collectionService.create(context, com); + collectionService.addMetadata(context, collectionPerson, "dspace", "entity", "type", + null, "Person"); + collectionPerson.setSubmitters(submitters); + groupService.addMember(context, submitters, epersonA); + context.setCurrentUser(epersonA); + context.commit(); + context.restoreAuthSystemState(); + Collection resultCollection = collectionService.retrieveCollectionWithSubmitByCommunityAndEntityType + (context, com, "Person"); + + assertThat("testRetrieveCollectionWithSubmitByEntityType 0", resultCollection, notNullValue()); + assertThat("testRetrieveCollectionWithSubmitByEntityType 1", resultCollection, equalTo(collectionPerson)); + + context.setDispatcher("exclude-discovery"); + } } diff --git a/dspace-api/src/test/java/org/dspace/external/MockOpenAIRERestConnector.java b/dspace-api/src/test/java/org/dspace/external/MockOpenaireRestConnector.java similarity index 90% rename from dspace-api/src/test/java/org/dspace/external/MockOpenAIRERestConnector.java rename to dspace-api/src/test/java/org/dspace/external/MockOpenaireRestConnector.java index bac80e196c..c67402dfdc 100644 --- a/dspace-api/src/test/java/org/dspace/external/MockOpenAIRERestConnector.java +++ b/dspace-api/src/test/java/org/dspace/external/MockOpenaireRestConnector.java @@ -14,15 +14,15 @@ import eu.openaire.jaxb.helper.OpenAIREHandler; import eu.openaire.jaxb.model.Response; /** - * Mock the OpenAIRE rest connector for unit testing
+ * Mock the Openaire rest connector for unit testing
* will be resolved against static test xml files * * @author pgraca * */ -public class MockOpenAIRERestConnector extends OpenAIRERestConnector { +public class MockOpenaireRestConnector extends OpenaireRestConnector { - public MockOpenAIRERestConnector(String url) { + public MockOpenaireRestConnector(String url) { super(url); } diff --git a/dspace-api/src/test/java/org/dspace/external/provider/impl/OpenAIREFundingDataProviderTest.java b/dspace-api/src/test/java/org/dspace/external/provider/impl/OpenaireFundingDataProviderTest.java similarity index 59% rename from dspace-api/src/test/java/org/dspace/external/provider/impl/OpenAIREFundingDataProviderTest.java rename to dspace-api/src/test/java/org/dspace/external/provider/impl/OpenaireFundingDataProviderTest.java index 5e96f06ac8..d14dc99035 100644 --- a/dspace-api/src/test/java/org/dspace/external/provider/impl/OpenAIREFundingDataProviderTest.java +++ b/dspace-api/src/test/java/org/dspace/external/provider/impl/OpenaireFundingDataProviderTest.java @@ -23,15 +23,15 @@ import org.junit.Before; import org.junit.Test; /** - * Unit tests for OpenAIREFundingDataProvider + * Unit tests for OpenaireFundingDataProvider * * @author pgraca * */ -public class OpenAIREFundingDataProviderTest extends AbstractDSpaceTest { +public class OpenaireFundingDataProviderTest extends AbstractDSpaceTest { ExternalDataService externalDataService; - ExternalDataProvider openAIREFundingDataProvider; + ExternalDataProvider openaireFundingDataProvider; /** * This method will be run before every test as per @Before. It will initialize @@ -44,38 +44,38 @@ public class OpenAIREFundingDataProviderTest extends AbstractDSpaceTest { public void init() { // Set up External Service Factory and set data providers externalDataService = ExternalServiceFactory.getInstance().getExternalDataService(); - openAIREFundingDataProvider = externalDataService.getExternalDataProvider("openAIREFunding"); + openaireFundingDataProvider = externalDataService.getExternalDataProvider("openaireFunding"); } @Test public void testNumberOfResultsWSingleKeyword() { - assertNotNull("openAIREFundingDataProvider is not null", openAIREFundingDataProvider); - assertEquals("openAIREFunding.numberOfResults.query:mock", 77, - openAIREFundingDataProvider.getNumberOfResults("mock")); + assertNotNull("openaireFundingDataProvider is not null", openaireFundingDataProvider); + assertEquals("openaireFunding.numberOfResults.query:mock", 77, + openaireFundingDataProvider.getNumberOfResults("mock")); } @Test public void testNumberOfResultsWKeywords() { - assertNotNull("openAIREFundingDataProvider is not null", openAIREFundingDataProvider); - assertEquals("openAIREFunding.numberOfResults.query:mock+test", 77, - openAIREFundingDataProvider.getNumberOfResults("mock+test")); + assertNotNull("openaireFundingDataProvider is not null", openaireFundingDataProvider); + assertEquals("openaireFunding.numberOfResults.query:mock+test", 77, + openaireFundingDataProvider.getNumberOfResults("mock+test")); } @Test public void testQueryResultsWSingleKeyword() { - assertNotNull("openAIREFundingDataProvider is not null", openAIREFundingDataProvider); - List results = openAIREFundingDataProvider.searchExternalDataObjects("mock", 0, 10); - assertEquals("openAIREFunding.searchExternalDataObjects.size", 10, results.size()); + assertNotNull("openaireFundingDataProvider is not null", openaireFundingDataProvider); + List results = openaireFundingDataProvider.searchExternalDataObjects("mock", 0, 10); + assertEquals("openaireFunding.searchExternalDataObjects.size", 10, results.size()); } @Test public void testQueryResultsWKeywords() { String value = "Mushroom Robo-Pic - Development of an autonomous robotic mushroom picking system"; - assertNotNull("openAIREFundingDataProvider is not null", openAIREFundingDataProvider); - List results = openAIREFundingDataProvider.searchExternalDataObjects("mock+test", 0, 10); - assertEquals("openAIREFunding.searchExternalDataObjects.size", 10, results.size()); - assertTrue("openAIREFunding.searchExternalDataObjects.first.value", value.equals(results.get(0).getValue())); + assertNotNull("openaireFundingDataProvider is not null", openaireFundingDataProvider); + List results = openaireFundingDataProvider.searchExternalDataObjects("mock+test", 0, 10); + assertEquals("openaireFunding.searchExternalDataObjects.size", 10, results.size()); + assertTrue("openaireFunding.searchExternalDataObjects.first.value", value.equals(results.get(0).getValue())); } @Test @@ -84,22 +84,22 @@ public class OpenAIREFundingDataProviderTest extends AbstractDSpaceTest { String value = "Portuguese Wild Mushrooms: Chemical characterization and functional study" + " of antiproliferative and proapoptotic properties in cancer cell lines"; - assertNotNull("openAIREFundingDataProvider is not null", openAIREFundingDataProvider); + assertNotNull("openaireFundingDataProvider is not null", openaireFundingDataProvider); - Optional result = openAIREFundingDataProvider.getExternalDataObject(id); + Optional result = openaireFundingDataProvider.getExternalDataObject(id); - assertTrue("openAIREFunding.getExternalDataObject.exists", result.isPresent()); - assertTrue("openAIREFunding.getExternalDataObject.value", value.equals(result.get().getValue())); + assertTrue("openaireFunding.getExternalDataObject.exists", result.isPresent()); + assertTrue("openaireFunding.getExternalDataObject.value", value.equals(result.get().getValue())); } @Test public void testGetDataObjectWInvalidId() { String id = "WRONGID"; - assertNotNull("openAIREFundingDataProvider is not null", openAIREFundingDataProvider); + assertNotNull("openaireFundingDataProvider is not null", openaireFundingDataProvider); - Optional result = openAIREFundingDataProvider.getExternalDataObject(id); + Optional result = openaireFundingDataProvider.getExternalDataObject(id); - assertTrue("openAIREFunding.getExternalDataObject.notExists:WRONGID", result.isEmpty()); + assertTrue("openaireFunding.getExternalDataObject.notExists:WRONGID", result.isEmpty()); } } diff --git a/dspace-api/src/test/java/org/dspace/qaevent/script/OpenaireEventsImportIT.java b/dspace-api/src/test/java/org/dspace/qaevent/script/OpenaireEventsImportIT.java index de81d63fe1..b73111ba14 100644 --- a/dspace-api/src/test/java/org/dspace/qaevent/script/OpenaireEventsImportIT.java +++ b/dspace-api/src/test/java/org/dspace/qaevent/script/OpenaireEventsImportIT.java @@ -50,9 +50,9 @@ import org.dspace.matcher.QASourceMatcher; import org.dspace.matcher.QATopicMatcher; import org.dspace.qaevent.QANotifyPatterns; import org.dspace.qaevent.QATopic; -import org.dspace.qaevent.service.BrokerClientFactory; +import org.dspace.qaevent.service.OpenaireClientFactory; import org.dspace.qaevent.service.QAEventService; -import org.dspace.qaevent.service.impl.BrokerClientFactoryImpl; +import org.dspace.qaevent.service.impl.OpenaireClientFactoryImpl; import org.dspace.services.ConfigurationService; import org.dspace.utils.DSpace; import org.junit.After; @@ -71,11 +71,13 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase private static final String BASE_JSON_DIR_PATH = "org/dspace/app/openaire-events/"; + private static final String ORDER_FIELD = "topic"; + private QAEventService qaEventService = new DSpace().getSingletonService(QAEventService.class); private Collection collection; - private BrokerClient brokerClient = BrokerClientFactory.getInstance().getBrokerClient(); + private BrokerClient brokerClient = OpenaireClientFactory.getInstance().getBrokerClient(); private BrokerClient mockBrokerClient = mock(BrokerClient.class); @@ -101,12 +103,12 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase context.restoreAuthSystemState(); configurationService.setProperty("qaevent.sources", new String[] { QAEvent.OPENAIRE_SOURCE }); - ((BrokerClientFactoryImpl) BrokerClientFactory.getInstance()).setBrokerClient(mockBrokerClient); + ((OpenaireClientFactoryImpl) OpenaireClientFactory.getInstance()).setBrokerClient(mockBrokerClient); } @After public void after() { - ((BrokerClientFactoryImpl) BrokerClientFactory.getInstance()).setBrokerClient(brokerClient); + ((OpenaireClientFactoryImpl) OpenaireClientFactory.getInstance()).setBrokerClient(brokerClient); } @Test @@ -174,7 +176,8 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 5L)) ); - List topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20); + List topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20, + ORDER_FIELD, false); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PID, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_PID, 1L))); @@ -235,7 +238,8 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 3L))); - List topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20); + List topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20, + ORDER_FIELD, false); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_PROJECT, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PID, 1L))); @@ -276,7 +280,7 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 1L))); - assertThat(qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20), + assertThat(qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20, ORDER_FIELD, false), contains(QATopicMatcher.with(org.dspace.qaevent.QANotifyPatterns.TOPIC_ENRICH_MISSING_ABSTRACT, 1L))); String abstractMessage = "{\"abstracts[0]\":\"Missing Abstract\"}"; @@ -306,7 +310,7 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 0L))); - assertThat(qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20), empty()); + assertThat(qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20, ORDER_FIELD, false), empty()); verifyNoInteractions(mockBrokerClient); } @@ -353,7 +357,8 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 6L))); - List topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20); + List topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20, + ORDER_FIELD, false); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PID, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_PID, 1L))); @@ -412,7 +417,7 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 0L))); - assertThat(qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20), empty()); + assertThat(qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20, ORDER_FIELD, false), empty()); verify(mockBrokerClient).listSubscriptions(openaireURL, "user@test.com"); @@ -463,7 +468,8 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(OPENAIRE_SOURCE, 6L))); - List topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20); + List topicList = qaEventService.findAllTopicsBySource(context, OPENAIRE_SOURCE, 0, 20, + ORDER_FIELD, false); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PROJECT, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MISSING_PID, 1L))); assertThat(topicList, hasItem(QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_PID, 1L))); @@ -505,7 +511,8 @@ public class OpenaireEventsImportIT extends AbstractIntegrationTestWithDatabase String[] args = new String[] { "import-openaire-events", "-f", getFileLocation("event-more-review.json") }; ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), handler, kernelImpl); - assertThat(qaEventService.findAllTopicsBySource(context, COAR_NOTIFY_SOURCE, 0, 20), contains( + assertThat(qaEventService.findAllTopicsBySource(context, COAR_NOTIFY_SOURCE, 0, 20, + ORDER_FIELD, false), contains( QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_REVIEW, 1L))); assertThat(qaEventService.findAllSources(context, 0, 20), diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java index fee77ee176..59782fd44b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java @@ -1093,6 +1093,17 @@ public class RestResourceController implements InitializingBean { return uriComponentsBuilder.encode().build().toString(); } + /** + * Method to delete an entity by ID + * Note that the regular expression in the request mapping accept a number as identifier; + * + * @param request + * @param apiCategory + * @param model + * @param id + * @return + * @throws HttpRequestMethodNotSupportedException + */ @RequestMapping(method = RequestMethod.DELETE, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT) public ResponseEntity> delete(HttpServletRequest request, @PathVariable String apiCategory, @PathVariable String model, @PathVariable Integer id) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/authorization/impl/QAAuthorizationFeature.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/authorization/impl/QAAuthorizationFeature.java new file mode 100644 index 0000000000..332c7a5989 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/authorization/impl/QAAuthorizationFeature.java @@ -0,0 +1,46 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest.authorization.impl; + +import java.sql.SQLException; + +import org.dspace.app.rest.authorization.AuthorizationFeature; +import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation; +import org.dspace.app.rest.model.BaseObjectRest; +import org.dspace.app.rest.model.SiteRest; +import org.dspace.core.Context; +import org.dspace.services.ConfigurationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * The QA Event feature. It can be used to verify if Quality Assurance can be seen. + * + * Authorization is granted if the current user has READ permissions on the given bitstream. + */ +@Component +@AuthorizationFeatureDocumentation(name = QAAuthorizationFeature.NAME, + description = "It can be used to verify if the user can manage Quality Assurance events") +public class QAAuthorizationFeature implements AuthorizationFeature { + public final static String NAME = "canSeeQA"; + + @Autowired + private ConfigurationService configurationService; + + @Override + public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException { + return configurationService.getBooleanProperty("qaevents.enabled", false); + } + + @Override + public String[] getSupportedTypes() { + return new String[]{ + SiteRest.CATEGORY + "." + SiteRest.NAME + }; + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRestRepository.java index ea51e0e5a3..c971e8e127 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/QAEventRestRepository.java @@ -24,7 +24,7 @@ import org.dspace.content.QAEvent; import org.dspace.content.service.ItemService; import org.dspace.core.Context; import org.dspace.eperson.EPerson; -import org.dspace.qaevent.dao.QAEventsDao; +import org.dspace.qaevent.dao.QAEventsDAO; import org.dspace.qaevent.service.QAEventService; import org.dspace.util.UUIDUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -48,7 +48,7 @@ public class QAEventRestRepository extends DSpaceRestRepository { + final static String ORDER_FIELD = "topic"; + @Autowired private QAEventService qaEventService; @@ -66,9 +69,14 @@ public class QATopicRestRepository extends DSpaceRestRepository findBySource(@Parameter(value = "source", required = true) String source, Pageable pageable) { Context context = obtainContext(); - List topics = qaEventService.findAllTopicsBySource(context, source, - pageable.getOffset(), pageable.getPageSize()); long count = qaEventService.countTopicsBySource(context, source); + boolean ascending = false; + if (pageable.getSort() != null && pageable.getSort().getOrderFor(ORDER_FIELD) != null) { + ascending = pageable.getSort() + .getOrderFor(ORDER_FIELD).getDirection() == Direction.ASC; + } + List topics = qaEventService.findAllTopics(context, pageable.getOffset(), pageable.getPageSize(), + ORDER_FIELD, ascending); if (topics == null) { return null; } @@ -82,8 +90,10 @@ public class QATopicRestRepository extends DSpaceRestRepository topics = qaEventService - .findAllTopicsBySourceAndTarget(context, source, target, pageable.getOffset(), pageable.getPageSize()); + .findAllTopicsBySourceAndTarget(context, source, target, pageable.getOffset(), + pageable.getPageSize(), null, true); long count = qaEventService.countTopicsBySourceAndTarget(context, source, target); + if (topics == null) { return null; } diff --git a/dspace-server-webapp/src/test/data/dspaceFolder/config/item-submission.xml b/dspace-server-webapp/src/test/data/dspaceFolder/config/item-submission.xml index eca9acf79f..e42b7386ab 100644 --- a/dspace-server-webapp/src/test/data/dspaceFolder/config/item-submission.xml +++ b/dspace-server-webapp/src/test/data/dspaceFolder/config/item-submission.xml @@ -135,28 +135,28 @@ fake.workflow.readonly org.dspace.submit.step.SampleStep sample workflow --> - - + + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form @@ -259,13 +259,13 @@ - - + + - - + + @@ -274,17 +274,17 @@ - + - + - + - + - + - + diff --git a/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/external-openaire.xml b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/external-openaire.xml index 9db02440e4..b045865fe0 100644 --- a/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/external-openaire.xml +++ b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/external-openaire.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true"> - + - - + + Project diff --git a/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/test-discovery.xml b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/test-discovery.xml index 4a91ef051e..ea654ac55c 100644 --- a/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/test-discovery.xml +++ b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/test-discovery.xml @@ -86,8 +86,8 @@ - - + + diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryVersioningIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryVersioningIT.java index 083b27d0e5..7b9cad70e9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryVersioningIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryVersioningIT.java @@ -1057,8 +1057,8 @@ public class DiscoveryVersioningIT extends AbstractControllerIntegrationTest { } @Test - public void test_discoveryXml_openAIREFundingAgency_expectLatestVersionsOnly() throws Exception { - final String configuration = "openAIREFundingAgency"; + public void test_discoveryXml_openaireFundingAgency_expectLatestVersionsOnly() throws Exception { + final String configuration = "openaireFundingAgency"; Collection collection = createCollection("OrgUnit"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ExternalSourcesRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ExternalSourcesRestControllerIT.java index f22eb94aa0..55cc99567f 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ExternalSourcesRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ExternalSourcesRestControllerIT.java @@ -52,7 +52,7 @@ public class ExternalSourcesRestControllerIT extends AbstractControllerIntegrati ExternalSourceMatcher.matchExternalSource( "pubmed", "pubmed", false), ExternalSourceMatcher.matchExternalSource( - "openAIREFunding", "openAIREFunding", false) + "openaireFunding", "openaireFunding", false) ))) .andExpect(jsonPath("$.page.totalElements", Matchers.is(11))); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java index 78a38bf887..ddce490e96 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/LDNInboxControllerIT.java @@ -130,7 +130,7 @@ public class LDNInboxControllerIT extends AbstractControllerIntegrationTest { assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(COAR_NOTIFY_SOURCE, 1L))); - assertThat(qaEventService.findAllTopicsBySource(context, COAR_NOTIFY_SOURCE, 0, 20), hasItem( + assertThat(qaEventService.findAllTopicsBySource(context, COAR_NOTIFY_SOURCE, 0, 20, "topic", true), hasItem( QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_REVIEW, 1L))); } @@ -237,7 +237,7 @@ public class LDNInboxControllerIT extends AbstractControllerIntegrationTest { assertThat(qaEventService.findAllSources(context, 0, 20), hasItem(QASourceMatcher.with(COAR_NOTIFY_SOURCE, 1L))); - assertThat(qaEventService.findAllTopicsBySource(context, COAR_NOTIFY_SOURCE, 0, 20), hasItem( + assertThat(qaEventService.findAllTopicsBySource(context, COAR_NOTIFY_SOURCE, 0, 20, "topic", true), hasItem( QATopicMatcher.with(QANotifyPatterns.TOPIC_ENRICH_MORE_LINK, 1L))); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OpenAIREFundingExternalSourcesIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OpenaireFundingExternalSourcesIT.java similarity index 83% rename from dspace-server-webapp/src/test/java/org/dspace/app/rest/OpenAIREFundingExternalSourcesIT.java rename to dspace-server-webapp/src/test/java/org/dspace/app/rest/OpenaireFundingExternalSourcesIT.java index b8f886b2e4..8c76c7adea 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OpenAIREFundingExternalSourcesIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OpenaireFundingExternalSourcesIT.java @@ -19,7 +19,7 @@ import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.hamcrest.Matchers; import org.junit.Test; -public class OpenAIREFundingExternalSourcesIT extends AbstractControllerIntegrationTest { +public class OpenaireFundingExternalSourcesIT extends AbstractControllerIntegrationTest { /** * Test openaire funding external source @@ -27,10 +27,10 @@ public class OpenAIREFundingExternalSourcesIT extends AbstractControllerIntegrat * @throws Exception */ @Test - public void findOneOpenAIREFundingExternalSourceTest() throws Exception { + public void findOneOpenaireFundingExternalSourceTest() throws Exception { getClient().perform(get("/api/integration/externalsources")).andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.externalsources", Matchers.hasItem( - ExternalSourceMatcher.matchExternalSource("openAIREFunding", "openAIREFunding", false)))); + ExternalSourceMatcher.matchExternalSource("openaireFunding", "openaireFunding", false)))); } /** @@ -39,9 +39,9 @@ public class OpenAIREFundingExternalSourcesIT extends AbstractControllerIntegrat * @throws Exception */ @Test - public void findOneOpenAIREFundingExternalSourceEntriesEmptyWithQueryTest() throws Exception { + public void findOneOpenaireFundingExternalSourceEntriesEmptyWithQueryTest() throws Exception { - getClient().perform(get("/api/integration/externalsources/openAIREFunding/entries").param("query", "empty")) + getClient().perform(get("/api/integration/externalsources/openaireFunding/entries").param("query", "empty")) .andExpect(status().isOk()).andExpect(jsonPath("$.page.number", is(0))); } @@ -52,11 +52,11 @@ public class OpenAIREFundingExternalSourcesIT extends AbstractControllerIntegrat * @throws Exception */ @Test - public void findOneOpenAIREFundingExternalSourceEntriesWithQueryMultipleKeywordsTest() throws Exception { + public void findOneOpenaireFundingExternalSourceEntriesWithQueryMultipleKeywordsTest() throws Exception { getClient() .perform( - get("/api/integration/externalsources/openAIREFunding/entries").param("query", "empty+results")) + get("/api/integration/externalsources/openaireFunding/entries").param("query", "empty+results")) .andExpect(status().isOk()).andExpect(jsonPath("$.page.number", is(0))); } @@ -66,14 +66,14 @@ public class OpenAIREFundingExternalSourcesIT extends AbstractControllerIntegrat * @throws Exception */ @Test - public void findOneOpenAIREFundingExternalSourceEntriesWithQueryTest() throws Exception { - getClient().perform(get("/api/integration/externalsources/openAIREFunding/entries").param("query", "mushroom")) + public void findOneOpenaireFundingExternalSourceEntriesWithQueryTest() throws Exception { + getClient().perform(get("/api/integration/externalsources/openaireFunding/entries").param("query", "mushroom")) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.externalSourceEntries", Matchers.hasItem(ExternalSourceEntryMatcher.matchExternalSourceEntry( "aW5mbzpldS1yZXBvL2dyYW50QWdyZWVtZW50L05XTy8rLzIzMDAxNDc3MjgvTkw=", "Master switches of initiation of mushroom formation", - "Master switches of initiation of mushroom formation", "openAIREFunding")))); + "Master switches of initiation of mushroom formation", "openaireFunding")))); } @@ -83,19 +83,19 @@ public class OpenAIREFundingExternalSourcesIT extends AbstractControllerIntegrat * @throws Exception */ @Test - public void findOneOpenAIREFundingExternalSourceEntryValueTest() throws Exception { + public void findOneOpenaireFundingExternalSourceEntryValueTest() throws Exception { // "info:eu-repo/grantAgreement/mock/mock/mock/mock" base64 encoded String projectID = "aW5mbzpldS1yZXBvL2dyYW50QWdyZWVtZW50L0ZDVC81ODc2LVBQQ0RUSS8xMTAwNjIvUFQ="; String projectName = "Portuguese Wild Mushrooms: Chemical characterization and functional study" + " of antiproliferative and proapoptotic properties in cancer cell lines"; - getClient().perform(get("/api/integration/externalsources/openAIREFunding/entryValues/" + projectID)) + getClient().perform(get("/api/integration/externalsources/openaireFunding/entryValues/" + projectID)) .andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.allOf(hasJsonPath("$.id", is(projectID)), hasJsonPath("$.display", is(projectName)), hasJsonPath("$.value", is(projectName)), - hasJsonPath("$.externalSource", is("openAIREFunding")), + hasJsonPath("$.externalSource", is("openaireFunding")), hasJsonPath("$.type", is("externalSourceEntry"))))); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/QAEventRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/QAEventRestRepositoryIT.java index aca12ffbde..e6b96acd8d 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/QAEventRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/QAEventRestRepositoryIT.java @@ -56,7 +56,7 @@ import org.dspace.content.service.ItemService; import org.dspace.eperson.EPerson; import org.dspace.qaevent.QANotifyPatterns; import org.dspace.qaevent.action.ASimpleMetadataAction; -import org.dspace.qaevent.dao.QAEventsDao; +import org.dspace.qaevent.dao.QAEventsDAO; import org.hamcrest.Matchers; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -70,7 +70,7 @@ import org.springframework.beans.factory.annotation.Autowired; public class QAEventRestRepositoryIT extends AbstractControllerIntegrationTest { @Autowired - private QAEventsDao qaEventsDao; + private QAEventsDAO qaEventsDao; @Autowired private ItemService itemService; @@ -1002,6 +1002,11 @@ public class QAEventRestRepositoryIT extends AbstractControllerIntegrationTest { .withMessage("{\"pids[0].type\":\"doi\",\"pids[0].value\":\"10.2307/2144300\"}") .build(); + QAEvent event2 = QAEventBuilder.createTarget(context, col1, "Science and Freedom") + .withTopic("ENRICH/MISSING/PID") + .withMessage("{\"pids[0].type\":\"doi\",\"pids[0].value\":\"10.2307/2144300\"}") + .build(); + context.restoreAuthSystemState(); String authToken = getAuthToken(admin.getEmail(), password); @@ -1029,6 +1034,12 @@ public class QAEventRestRepositoryIT extends AbstractControllerIntegrationTest { assertThat(processedEvent.getEventTimestamp(), notNullValue()); assertThat(processedEvent.getEperson().getID(), is(admin.getID())); + getClient(authToken).perform(delete("/api/integration/qualityassuranceevents/" + event.getEventId())) + .andExpect(status().isInternalServerError()); + + authToken = getAuthToken(eperson.getEmail(), password); + getClient(authToken).perform(delete("/api/integration/qualityassuranceevents/" + event2.getEventId())) + .andExpect(status().isForbidden()); } @Test diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SitemapRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SitemapRestControllerIT.java index 175fb34e6c..04d22718e8 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SitemapRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SitemapRestControllerIT.java @@ -216,7 +216,12 @@ public class SitemapRestControllerIT extends AbstractControllerIntegrationTest { //** THEN ** .andExpect(status().isOk()) //We expect the content type to match - .andExpect(content().contentType("application/xml;charset=UTF-8")) + .andExpect(res -> { + String actual = res.getResponse().getContentType(); + assertTrue("Content Type", + "text/xml;charset=UTF-8".equals(actual) || + "application/xml;charset=UTF-8".equals(actual)); + }) .andReturn(); String response = result.getResponse().getContentAsString(); @@ -232,7 +237,12 @@ public class SitemapRestControllerIT extends AbstractControllerIntegrationTest { //** THEN ** .andExpect(status().isOk()) //We expect the content type to match - .andExpect(content().contentType("application/xml;charset=UTF-8")) + .andExpect(res -> { + String actual = res.getResponse().getContentType(); + assertTrue("Content Type", + "text/xml;charset=UTF-8".equals(actual) || + "application/xml;charset=UTF-8".equals(actual)); + }) .andReturn(); String response = result.getResponse().getContentAsString(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/QAAuthorizationFeatureIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/QAAuthorizationFeatureIT.java new file mode 100644 index 0000000000..f3e508485a --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/authorization/QAAuthorizationFeatureIT.java @@ -0,0 +1,84 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest.authorization; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.dspace.app.rest.authorization.impl.QAAuthorizationFeature; +import org.dspace.app.rest.converter.SiteConverter; +import org.dspace.app.rest.matcher.AuthorizationMatcher; +import org.dspace.app.rest.model.SiteRest; +import org.dspace.app.rest.projection.DefaultProjection; +import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.content.Site; +import org.dspace.content.service.SiteService; +import org.dspace.services.ConfigurationService; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Test suite for the Quality Assurance Authorization feature + * + * @author Francesco Bacchelli (francesco.bacchelli at 4science.it) + * + */ +public class QAAuthorizationFeatureIT extends AbstractControllerIntegrationTest { + + @Autowired + private AuthorizationFeatureService authorizationFeatureService; + + @Autowired + private SiteService siteService; + + @Autowired + private SiteConverter siteConverter; + + @Autowired + private ConfigurationService configurationService; + + + private AuthorizationFeature qaAuthorizationFeature; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + context.turnOffAuthorisationSystem(); + qaAuthorizationFeature = authorizationFeatureService.find(QAAuthorizationFeature.NAME); + context.restoreAuthSystemState(); + } + + @Test + public void testQAAuthorizationSuccess() throws Exception { + configurationService.setProperty("qaevents.enabled", true); + Site site = siteService.findSite(context); + SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); + String tokenAdmin = getAuthToken(admin.getEmail(), password); + Authorization authAdminSite = new Authorization(admin, qaAuthorizationFeature, siteRest); + + getClient(tokenAdmin).perform(get("/api/authz/authorizations/" + authAdminSite.getID())) + .andExpect(jsonPath("$", Matchers.is( + AuthorizationMatcher.matchAuthorization(authAdminSite)))); + } + + @Test + public void testQAAuthorizationFail() throws Exception { + configurationService.setProperty("qaevents.enabled", false); + Site site = siteService.findSite(context); + SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT); + String tokenAdmin = getAuthToken(admin.getEmail(), password); + Authorization authAdminSite = new Authorization(admin, qaAuthorizationFeature, siteRest); + + getClient(tokenAdmin).perform(get("/api/authz/authorizations/" + authAdminSite.getID())) + .andExpect(status().isNotFound()); + } +} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/QAEventMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/QAEventMatcher.java index f34356d723..88a09157b8 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/QAEventMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/QAEventMatcher.java @@ -143,7 +143,7 @@ public class QAEventMatcher { hrefPrefix = "https://arxiv.org/abs/"; break; case "handle": - hrefPrefix = "https://arxiv.org/abs/"; + hrefPrefix = "https://hdl.handle.net/"; break; case "urn": hrefPrefix = ""; diff --git a/dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockOpenAIREFundingDataProvider.java b/dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockOpenaireFundingDataProvider.java similarity index 91% rename from dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockOpenAIREFundingDataProvider.java rename to dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockOpenaireFundingDataProvider.java index baf1041ab5..34f1ae16c7 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockOpenAIREFundingDataProvider.java +++ b/dspace-server-webapp/src/test/java/org/dspace/external/provider/impl/MockOpenaireFundingDataProvider.java @@ -14,7 +14,7 @@ import javax.xml.bind.JAXBException; import eu.openaire.jaxb.helper.OpenAIREHandler; import eu.openaire.jaxb.model.Response; -import org.dspace.external.OpenAIRERestConnector; +import org.dspace.external.OpenaireRestConnector; import org.mockito.AdditionalMatchers; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; @@ -22,14 +22,14 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; /** - * Mock the OpenAIRE external source using a mock rest connector so that query + * Mock the Openaire external source using a mock rest connector so that query * will be resolved against static test files * */ -public class MockOpenAIREFundingDataProvider extends OpenAIREFundingDataProvider { +public class MockOpenaireFundingDataProvider extends OpenaireFundingDataProvider { @Override public void init() throws IOException { - OpenAIRERestConnector restConnector = Mockito.mock(OpenAIRERestConnector.class); + OpenaireRestConnector restConnector = Mockito.mock(OpenaireRestConnector.class); when(restConnector.searchProjectByKeywords(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt(), ArgumentMatchers.startsWith("mushroom"))).thenAnswer(new Answer() { diff --git a/dspace/config/crosswalks/oai/transformers/openaire4.xsl b/dspace/config/crosswalks/oai/transformers/openaire4.xsl index cece890450..8ac703609d 100644 --- a/dspace/config/crosswalks/oai/transformers/openaire4.xsl +++ b/dspace/config/crosswalks/oai/transformers/openaire4.xsl @@ -1,5 +1,5 @@ - + @@ -12,7 +12,7 @@ - + - + @@ -66,12 +66,12 @@ - This contexts complies with OpenAIRE Guidelines for Literature Repositories v3.0. + This contexts complies with Openaire Guidelines for Literature Repositories v3.0. - + - - + + - This contexts complies with OpenAIRE Guidelines for Literature Repositories v4.0. + This contexts complies with Openaire Guidelines for Literature Repositories v4.0. @@ -176,7 +176,7 @@ http://irdb.nii.ac.jp/oai http://irdb.nii.ac.jp/oai/junii2-3-1.xsd - @@ -250,13 +250,13 @@ - @@ -319,7 +319,7 @@ - - + @@ -457,7 +457,7 @@ + OR "openAccess", which is required by Openaire. --> org.dspace.xoai.filter.DSpaceAtLeastOneMetadataFilter @@ -483,7 +483,7 @@ + which specifies the openaire project ID. --> org.dspace.xoai.filter.DSpaceAtLeastOneMetadataFilter diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index 6dc586f340..4fc67d7bac 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -185,28 +185,28 @@ extract - - + + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form @@ -371,13 +371,13 @@ - - + + - - + + @@ -386,17 +386,17 @@ - + - + - + - + - + - + diff --git a/dspace/config/modules/openaire-client.cfg b/dspace/config/modules/openaire-client.cfg index ded99d0120..b43ef781ee 100644 --- a/dspace/config/modules/openaire-client.cfg +++ b/dspace/config/modules/openaire-client.cfg @@ -16,20 +16,20 @@ # The accessToken it only has a validity of one hour # For more details about the token, please check: https://develop.openaire.eu/personalToken.html # -# the current OpenAIRE Rest client implementation uses basic authentication +# the current Openaire Rest client implementation uses basic authentication # Described here: https://develop.openaire.eu/basic.html # # ---- Token usage required definitions ---- # you can override this settings in your local.cfg file - can be true/false openaire.token.enabled = false -# URL of the OpenAIRE authentication and authorization service +# URL of the Openaire authentication and authorization service openaire.token.url = https://aai.openaire.eu/oidc/token -# you will be required to register at OpenAIRE (https://services.openaire.eu/uoa-user-management/registeredServices) +# you will be required to register at Openaire (https://services.openaire.eu/uoa-user-management/registeredServices) # and create your service in order to get the following data: openaire.token.clientId = CLIENT_ID_HERE openaire.token.clientSecret = CLIENT_SECRET_HERE -# URL of OpenAIRE Rest API +# URL of Openaire Rest API openaire.api.url = https://api.openaire.eu \ No newline at end of file diff --git a/dspace/config/modules/qaevents.cfg b/dspace/config/modules/qaevents.cfg index df3254f38d..28cf0f35dc 100644 --- a/dspace/config/modules/qaevents.cfg +++ b/dspace/config/modules/qaevents.cfg @@ -3,10 +3,11 @@ #---------------------------------------------------------------# # Configuration properties used by data correction service # #---------------------------------------------------------------# +# Quality Assurance enable property, false by default +qaevents.enabled = false qaevents.solr.server = ${solr.server}/${solr.multicorePrefix}qaevent # A POST to these url(s) will be done to notify oaire of decision taken for each qaevents -qaevents.openaire.acknowledge-url = https://beta.api-broker.openaire.eu/feedback/events -#qaevents.openaire.acknowledge-url +# qaevents.openaire.acknowledge-url = https://beta.api-broker.openaire.eu/feedback/events # The list of the supported events incoming from openaire (see also dspace/config/spring/api/qaevents.xml) # add missing abstract suggestion diff --git a/dspace/config/registries/openaire4-types.xml b/dspace/config/registries/openaire4-types.xml index b9499dd858..26d818a123 100644 --- a/dspace/config/registries/openaire4-types.xml +++ b/dspace/config/registries/openaire4-types.xml @@ -2,13 +2,13 @@ - OpenAIRE4 fields definition + Openaire4 fields definition @@ -102,4 +102,21 @@ The date when the conference took place. This property is considered to be part of the bibliographic citation. Recommended best practice for encoding the date value is defined in a profile of ISO 8601 [W3CDTF] and follows the YYYY-MM-DD format. + + + datacite + geoLocation + Spatial region or named place where the data was gathered or about which the data is focused. + + + + + datacite + subject + fos + Fields of Science and Technology - OECD + + diff --git a/dspace/config/registries/relationship-formats.xml b/dspace/config/registries/relationship-formats.xml index f2f50182fa..53d15d4d43 100644 --- a/dspace/config/registries/relationship-formats.xml +++ b/dspace/config/registries/relationship-formats.xml @@ -237,7 +237,7 @@ Contains all uuids of PUBLICATIONS which link to the current ISSUE via a "latest" relationship. In other words, this stores all relationships pointing to the current ISSUE from any PUBLICATION, implying that the ISSUE is marked as "latest". Internally used by DSpace to support versioning. Do not manually add, remove or edit values. - + relation diff --git a/dspace/config/registries/schema-organization-types.xml b/dspace/config/registries/schema-organization-types.xml index 91ee203ae9..0b31851078 100644 --- a/dspace/config/registries/schema-organization-types.xml +++ b/dspace/config/registries/schema-organization-types.xml @@ -42,10 +42,10 @@ - + - + organization diff --git a/dspace/config/registries/schema-person-types.xml b/dspace/config/registries/schema-person-types.xml index 3a8f79732d..0a40060e51 100644 --- a/dspace/config/registries/schema-person-types.xml +++ b/dspace/config/registries/schema-person-types.xml @@ -17,7 +17,7 @@ --> @@ -29,7 +29,7 @@ @@ -74,7 +74,7 @@ @@ -84,10 +84,10 @@ The organizational or institutional affiliation of the creator - + - + person identifier diff --git a/dspace/config/registries/schema-project-types.xml b/dspace/config/registries/schema-project-types.xml index c2f844d2b2..4da07b6a79 100644 --- a/dspace/config/registries/schema-project-types.xml +++ b/dspace/config/registries/schema-project-types.xml @@ -18,7 +18,7 @@ --> @@ -29,7 +29,7 @@ diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index fb25f11598..83896feb45 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -110,8 +110,8 @@ - - + + @@ -2027,7 +2027,7 @@
- diff --git a/dspace/config/spring/api/external-openaire.xml b/dspace/config/spring/api/external-openaire.xml index 25a23a1739..9800e42bd1 100644 --- a/dspace/config/spring/api/external-openaire.xml +++ b/dspace/config/spring/api/external-openaire.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/util/spring-util.xsd" default-lazy-init="true"> - + @@ -15,9 +15,9 @@ - - - + + + diff --git a/dspace/config/spring/api/item-filters.xml b/dspace/config/spring/api/item-filters.xml index 24c463fb53..1460c19fe4 100644 --- a/dspace/config/spring/api/item-filters.xml +++ b/dspace/config/spring/api/item-filters.xml @@ -286,7 +286,7 @@ - @@ -329,7 +329,7 @@ - diff --git a/dspace/config/spring/api/qaevents.xml b/dspace/config/spring/api/qaevents.xml index 663b1f1e9f..0ebc13d5b0 100644 --- a/dspace/config/spring/api/qaevents.xml +++ b/dspace/config/spring/api/qaevents.xml @@ -12,11 +12,11 @@ - + - + diff --git a/dspace/config/spring/api/scripts.xml b/dspace/config/spring/api/scripts.xml index d4b05e8448..2fb57fab6f 100644 --- a/dspace/config/spring/api/scripts.xml +++ b/dspace/config/spring/api/scripts.xml @@ -5,7 +5,7 @@ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> - + diff --git a/dspace/config/spring/rest/scripts.xml b/dspace/config/spring/rest/scripts.xml index c32ea8d40b..e6a667697d 100644 --- a/dspace/config/spring/rest/scripts.xml +++ b/dspace/config/spring/rest/scripts.xml @@ -9,7 +9,7 @@ - + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 39a4778356..d888e0990e 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -819,9 +819,9 @@ - + -
+ dc @@ -1071,7 +1071,7 @@
-
+ dc @@ -1129,7 +1129,7 @@ relation onebox - openAIREFunding + openaireFunding @@ -1182,7 +1182,7 @@
-
+ person @@ -1246,7 +1246,7 @@
-
+ dc @@ -1269,7 +1269,7 @@ isFundingAgencyOfProject - openAIREFundingAgency + openaireFundingAgency false false @@ -1302,7 +1302,7 @@ -
+ organization @@ -1537,7 +1537,7 @@ - + @@ -1579,7 +1579,7 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/dspace/src/main/docker/dspace-solr/Dockerfile b/dspace/src/main/docker/dspace-solr/Dockerfile index 9fe9adf944..5d02d0db81 100644 --- a/dspace/src/main/docker/dspace-solr/Dockerfile +++ b/dspace/src/main/docker/dspace-solr/Dockerfile @@ -17,19 +17,22 @@ FROM solr:${SOLR_VERSION}-slim ENV AUTHORITY_CONFIGSET_PATH=/opt/solr/server/solr/configsets/authority/conf \ OAI_CONFIGSET_PATH=/opt/solr/server/solr/configsets/oai/conf \ SEARCH_CONFIGSET_PATH=/opt/solr/server/solr/configsets/search/conf \ - STATISTICS_CONFIGSET_PATH=/opt/solr/server/solr/configsets/statistics/conf - + STATISTICS_CONFIGSET_PATH=/opt/solr/server/solr/configsets/statistics/conf \ + QAEVENT_CONFIGSET_PATH=/opt/solr/server/solr/configsets/qaevent/conf + USER root RUN mkdir -p $AUTHORITY_CONFIGSET_PATH && \ mkdir -p $OAI_CONFIGSET_PATH && \ mkdir -p $SEARCH_CONFIGSET_PATH && \ - mkdir -p $STATISTICS_CONFIGSET_PATH + mkdir -p $STATISTICS_CONFIGSET_PATH && \ + mkdir -p $QAEVENT_CONFIGSET_PATH COPY dspace/solr/authority/conf/* $AUTHORITY_CONFIGSET_PATH/ COPY dspace/solr/oai/conf/* $OAI_CONFIGSET_PATH/ COPY dspace/solr/search/conf/* $SEARCH_CONFIGSET_PATH/ COPY dspace/solr/statistics/conf/* $STATISTICS_CONFIGSET_PATH/ +COPY dspace/solr/qaevent/conf/* $QAEVENT_CONFIGSET_PATH/ RUN chown -R solr:solr /opt/solr/server/solr/configsets