CST-10638 reading data from database

This commit is contained in:
frabacche
2023-11-21 17:57:37 +01:00
parent 5537d5b19d
commit 48319a3301
13 changed files with 353 additions and 72 deletions

View File

@@ -11,6 +11,7 @@ import java.sql.SQLException;
import java.util.List;
import org.dspace.app.ldn.LDNMessageEntity;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.core.GenericDAO;
@@ -28,4 +29,9 @@ public interface LDNMessageDao extends GenericDAO<LDNMessageEntity> {
public List<LDNMessageEntity> findProcessingTimedoutMessages(Context context, int max_attempts) throws SQLException;
public List<LDNMessageEntity> findAllMessagesByItem(
Context context, Item item, String... activities) throws SQLException;
public List<LDNMessageEntity> findAllRelatedMessagesByItem(
Context context, String msgId, Item item, String... relatedTypes) throws SQLException;
}

View File

@@ -22,6 +22,7 @@ import org.apache.logging.log4j.Logger;
import org.dspace.app.ldn.LDNMessageEntity;
import org.dspace.app.ldn.LDNMessageEntity_;
import org.dspace.app.ldn.dao.LDNMessageDao;
import org.dspace.content.Item;
import org.dspace.core.AbstractHibernateDAO;
import org.dspace.core.Context;
@@ -85,4 +86,70 @@ public class LDNMessageDaoImpl extends AbstractHibernateDAO<LDNMessageEntity> im
}
return result;
}
@Override
public List<LDNMessageEntity> findAllRelatedMessagesByItem(
Context context, String msgId, Item item, String... relatedTypes) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery<LDNMessageEntity> criteriaQuery = getCriteriaQuery(criteriaBuilder, LDNMessageEntity.class);
Root<LDNMessageEntity> root = criteriaQuery.from(LDNMessageEntity.class);
criteriaQuery.select(root);
List<Predicate> andPredicates = new ArrayList<>();
Predicate relatedtypePredicate = null;
andPredicates.add(
criteriaBuilder.equal(root.get(LDNMessageEntity_.queueStatus), LDNMessageEntity.QUEUE_STATUS_PROCESSED));
andPredicates.add(
criteriaBuilder.equal(root.get(LDNMessageEntity_.object), item));
andPredicates.add(
criteriaBuilder.isNull(root.get(LDNMessageEntity_.target)));
andPredicates.add(
criteriaBuilder.equal(root.get(LDNMessageEntity_.inReplyTo), msgId));
if (relatedTypes != null && relatedTypes.length > 0) {
/*relatedtypePredicate = root.get(LDNMessageEntity_.activityStreamType).in(relatedTypes);
andPredicates.add(relatedtypePredicate);*/
}
criteriaQuery.where(criteriaBuilder.and(andPredicates.toArray(new Predicate[] {})));
List<Order> orderList = new LinkedList<>();
orderList.add(criteriaBuilder.asc(root.get(LDNMessageEntity_.queueLastStartTime)));
orderList.add(criteriaBuilder.desc(root.get(LDNMessageEntity_.queueAttempts)));
criteriaQuery.orderBy(orderList);
// setHint("org.hibernate.cacheable", Boolean.FALSE);
List<LDNMessageEntity> result = list(context, criteriaQuery, false, LDNMessageEntity.class, -1, -1);
if (result == null || result.isEmpty()) {
log.debug("No LDN messages ACK found to be processed");
}
return result;
}
@Override
public List<LDNMessageEntity> findAllMessagesByItem(
Context context, Item item, String... activities) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery<LDNMessageEntity> criteriaQuery = getCriteriaQuery(criteriaBuilder, LDNMessageEntity.class);
Root<LDNMessageEntity> root = criteriaQuery.from(LDNMessageEntity.class);
criteriaQuery.select(root);
List<Predicate> andPredicates = new ArrayList<>();
Predicate activityPredicate = null;
andPredicates.add(
criteriaBuilder.equal(root.get(LDNMessageEntity_.queueStatus), LDNMessageEntity.QUEUE_STATUS_PROCESSED));
andPredicates.add(
criteriaBuilder.equal(root.get(LDNMessageEntity_.object), item));
andPredicates.add(
criteriaBuilder.isNull(root.get(LDNMessageEntity_.origin)));
if (activities != null && activities.length > 0) {
/*activityPredicate = root.get(LDNMessageEntity_.activityStreamType).in(activities);
andPredicates.add(activityPredicate);*/
}
criteriaQuery.where(criteriaBuilder.and(andPredicates.toArray(new Predicate[] {})));
List<Order> orderList = new LinkedList<>();
orderList.add(criteriaBuilder.asc(root.get(LDNMessageEntity_.queueLastStartTime)));
orderList.add(criteriaBuilder.desc(root.get(LDNMessageEntity_.queueAttempts)));
criteriaQuery.orderBy(orderList);
// setHint("org.hibernate.cacheable", Boolean.FALSE);
List<LDNMessageEntity> result = list(context, criteriaQuery, false, LDNMessageEntity.class, -1, -1);
if (result == null || result.isEmpty()) {
log.debug("No LDN messages found");
}
return result;
}
}

View File

@@ -7,15 +7,15 @@
*/
package org.dspace.app.ldn.model;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonPropertyOrder(value = {
"itemuuid",
"endorsements",
"ingests",
"reviews"
"notifyStatus"
})
/**
@@ -25,14 +25,19 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
* "Offer", "coar-notify:IngestAction"
* "Offer", "coar-notify:ReviewAction"
*
* and their acknownledgements - if any
*
* @author Francesco Bacchelli (francesco.bacchelli at 4science dot it)
*/
public class NotifyRequestStatus extends Base {
private UUID itemUuid;
private List<RequestStatus> notifyStatus;
public NotifyRequestStatus() {
super();
this.notifyStatus = new ArrayList<RequestStatus>();
}
public UUID getItemUuid() {
@@ -43,6 +48,16 @@ public class NotifyRequestStatus extends Base {
this.itemUuid = itemUuid;
}
}
public void addRequestStatus(RequestStatus rs) {
this.notifyStatus.add(rs);
}
public List<RequestStatus> getNotifyStatus() {
return notifyStatus;
}
public void setNotifyStatus(List<RequestStatus> notifyStatus) {
this.notifyStatus = notifyStatus;
}
}

View File

@@ -0,0 +1,18 @@
/**
* 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.ldn.model;
/**
* REQUESTED means acknowledgements not received yet
* ACCEPTED means acknowledgements of "Accept" type received
* REJECTED means ack of "TentativeReject" type received
*
* @author Francesco Bacchelli (francesco.bacchelli at 4science.com)
*/
public enum NotifyRequestStatusEnum {
REJECTED, ACCEPTED, REQUESTED
}

View File

@@ -0,0 +1,40 @@
/**
* 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.ldn.model;
/**
* Informations about the Offer and Acknowledgements targeting a specified Item
*
* @author Francesco Bacchelli (francesco.bacchelli at 4science.com)
*/
public class RequestStatus {
private String serviceName;
private String serviceUrl;
private NotifyRequestStatusEnum status;
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getServiceUrl() {
return serviceUrl;
}
public void setServiceUrl(String serviceUrl) {
this.serviceUrl = serviceUrl;
}
public NotifyRequestStatusEnum getStatus() {
return status;
}
public void setStatus(NotifyRequestStatusEnum status) {
this.status = status;
}
}

View File

@@ -268,9 +268,12 @@ public class LDNMetadataProcessor implements LDNProcessor {
*/
private Item lookupItem(Context context, Notification notification) throws SQLException {
Item item = null;
String url = notification.getContext().getId();
String url = null;
if (notification.getContext() != null) {
url = notification.getContext().getId();
} else if (notification.getObject() != null) {
url = notification.getObject().getId();
}
log.info("Looking up item {}", url);
if (LDNUtils.hasUUIDInURL(url)) {

View File

@@ -9,13 +9,13 @@ package org.dspace.app.ldn.service;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import org.dspace.app.ldn.LDNMessageEntity;
import org.dspace.app.ldn.NotifyServiceEntity;
import org.dspace.app.ldn.model.Notification;
import org.dspace.app.ldn.model.NotifyRequestStatus;
import org.dspace.app.ldn.model.Service;
import org.dspace.content.Item;
import org.dspace.core.Context;
/**
@@ -113,9 +113,9 @@ public interface LDNMessageService {
* find the ldn messages of Requests by item uuid
*
* @param context the context
* @param itemId the item uuid
* @param item the item
* @return the item requests object
* @throws SQLException If something goes wrong in the database
*/
public NotifyRequestStatus findRequestsByItemUUID(Context context, UUID itemId) throws SQLException;
public NotifyRequestStatus findRequestsByItem(Context context, Item item) throws SQLException;
}

View File

@@ -28,17 +28,19 @@ import org.dspace.app.ldn.dao.LDNMessageDao;
import org.dspace.app.ldn.dao.NotifyServiceDao;
import org.dspace.app.ldn.model.Notification;
import org.dspace.app.ldn.model.NotifyRequestStatus;
import org.dspace.app.ldn.model.NotifyRequestStatusEnum;
import org.dspace.app.ldn.model.RequestStatus;
import org.dspace.app.ldn.model.Service;
import org.dspace.app.ldn.processor.LDNProcessor;
import org.dspace.app.ldn.service.LDNMessageService;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.dspace.handle.service.HandleService;
import org.dspace.services.ConfigurationService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Implementation of {@link LDNMessageService}
*
@@ -105,7 +107,9 @@ public class LDNMessageServiceImpl implements LDNMessageService {
// sorting the list
Collections.sort(notificationTypeArrayList);
ldnMessage.setActivityStreamType(notificationTypeArrayList.get(0));
ldnMessage.setCoarNotifyType(notificationTypeArrayList.get(1));
if (notificationTypeArrayList.size() > 1) {
ldnMessage.setCoarNotifyType(notificationTypeArrayList.get(1));
}
ldnMessage.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_QUEUED);
//CST-12126 if source is untrusted, set the queue_status of the
//ldnMsgEntity to UNTRUSTED
@@ -271,10 +275,34 @@ public class LDNMessageServiceImpl implements LDNMessageService {
}
@Override
public NotifyRequestStatus findRequestsByItemUUID(Context context, UUID itemId) throws SQLException {
public NotifyRequestStatus findRequestsByItem(Context context, Item item) throws SQLException {
NotifyRequestStatus result = new NotifyRequestStatus();
result.setItemUuid(itemId);
/* TODO SEARCH FOR LDN MESSAGES */
result.setItemUuid(item.getID());
List<LDNMessageEntity> msgs = ldnMessageDao.findAllMessagesByItem(
context, item, "Offer");
if (msgs != null && !msgs.isEmpty()) {
for (LDNMessageEntity msg : msgs) {
RequestStatus offer = new RequestStatus();
offer.setServiceName(msg.getCoarNotifyType());
offer.setServiceUrl(msg.getTarget().getLdnUrl());
String msgId = msg.getID();
List<LDNMessageEntity> acks = ldnMessageDao.findAllRelatedMessagesByItem(
context, msgId, item, "Accept", "TentativeReject", "TentativeAccept");
if (acks == null || acks.isEmpty()) {
offer.setStatus(NotifyRequestStatusEnum.REQUESTED);
} else if (acks.stream()
.filter(c -> (c.getActivityStreamType().equalsIgnoreCase("TentativeAccept") ||
c.getActivityStreamType().equalsIgnoreCase("Accept")))
.findAny().isPresent()) {
offer.setStatus(NotifyRequestStatusEnum.ACCEPTED);
} else if (acks.stream()
.filter(c -> c.getActivityStreamType().equalsIgnoreCase("TentativeReject"))
.findAny().isPresent()) {
offer.setStatus(NotifyRequestStatusEnum.REJECTED);
}
result.addRequestStatus(offer);
}
}
return result;
}
}

View File

@@ -5,7 +5,9 @@
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.repository;
package org.dspace.app.rest;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID;
import java.sql.SQLException;
import java.util.UUID;
@@ -14,60 +16,71 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.ldn.model.NotifyRequestStatus;
import org.dspace.app.ldn.service.LDNMessageService;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.model.NotifyRequestStatusRest;
import org.dspace.app.rest.model.hateoas.NotifyRequestStatusResource;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.data.rest.webmvc.ControllerUtils;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Rest Repository for LDN requests targeting items
* Rest Controller for NotifyRequestStatus targeting items
*
* @author Francesco Bacchelli (francesco.bacchelli at 4science dot it)
*/
@Component(NotifyRequestStatusRest.CATEGORY + "." + NotifyRequestStatusRest.NAME)
public class NotifyRequestStatusRestRepository extends DSpaceRestRepository<NotifyRequestStatusRest, String> {
@RestController
@RequestMapping("/api/" + NotifyRequestStatusRest.CATEGORY + "/" + NotifyRequestStatusRest.NAME +
REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID)
public class NotifyRequestStatusRestController {
private static final Logger log = LogManager.getLogger(NotifyRequestStatusRestRepository.class);
private static final Logger log = LogManager.getLogger(NotifyRequestStatusRestController.class);
@Autowired
private ConverterService converterService;
@Autowired
private Utils utils;
@Autowired
private LDNMessageService ldnMessageService;
@SearchRestMethod(name = NotifyRequestStatusRest.GET_ITEM_REQUESTS)
@Autowired
private ItemService itemService;
@GetMapping
//@PreAuthorize("hasAuthority('AUTHENTICATED')")
public NotifyRequestStatusRest findItemRequests(
@Parameter(value = "itemuuid", required = true) UUID itemUuid) {
public ResponseEntity<RepresentationModel<?>> findByItem(@PathVariable UUID uuid)
throws SQLException, AuthorizeException {
log.info("START findItemRequests looking for requests for item " + itemUuid);
Context context = obtainContext();
NotifyRequestStatus resultRequests = new NotifyRequestStatus();
try {
resultRequests = ldnMessageService.findRequestsByItemUUID(context, itemUuid);
} catch (SQLException e) {
log.error(e);
log.info("START findItemRequests looking for requests for item " + uuid);
Context context = ContextUtil.obtainCurrentRequestContext();
Item item = itemService.find(context, uuid);
if (item == null) {
throw new ResourceNotFoundException("No such item: " + uuid);
}
log.info("END findItemRequests");
return converter.toRest(resultRequests, utils.obtainProjection());
NotifyRequestStatus resultRequests = ldnMessageService.findRequestsByItem(context, item);
NotifyRequestStatusRest resultRequestStatusRests = converterService.toRest(
resultRequests, utils.obtainProjection());
NotifyRequestStatusResource resultRequestStatusResource = converterService.toResource(resultRequestStatusRests);
context.complete();
return ControllerUtils.toResponseEntity(HttpStatus.OK, new HttpHeaders(), resultRequestStatusResource);
}
@Override
public NotifyRequestStatusRest findOne(Context context, String id) {
// TODO Auto-generated method stub
return null;
}
@Override
public Page<NotifyRequestStatusRest> findAll(Context context, Pageable pageable) {
// TODO Auto-generated method stub
return null;
}
@Override
public Class<NotifyRequestStatusRest> getDomainClass() {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -13,7 +13,7 @@ import org.dspace.app.rest.projection.Projection;
import org.springframework.stereotype.Component;
/**
* This is the converter from/to the ItemRequests in the DSpace API data model and
* This is the converter from/to the NotifyRequestStatus in the DSpace API data model and
* the REST data model
*
* @author Francesco Bacchelli (francesco.bacchelli at 4science.it)
@@ -25,6 +25,7 @@ public class NotifyRequestStatusConverter implements DSpaceConverter<NotifyReque
public NotifyRequestStatusRest convert(NotifyRequestStatus modelObject, Projection projection) {
NotifyRequestStatusRest result = new NotifyRequestStatusRest();
result.setItemuuid(modelObject.getItemUuid());
result.setNotifyStatus(modelObject.getNotifyStatus());
return result;
}

View File

@@ -7,12 +7,15 @@
*/
package org.dspace.app.rest.model;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.dspace.app.rest.RestResourceController;
import org.dspace.app.ldn.model.RequestStatus;
import org.dspace.app.rest.NotifyRequestStatusRestController;
/**
* Rest entity for LDN requests targeting items
@@ -25,14 +28,18 @@ import org.dspace.app.rest.RestResourceController;
})
public class NotifyRequestStatusRest extends RestAddressableModel {
public static final String CATEGORY = RestAddressableModel.LDN;
public static final String NAME = "ldnitemservice";
public static final String GET_ITEM_REQUESTS = "getItemRequests";
public static final String NAME = "notifyrequests";
public static final String FIND_BY_ITEM = "findbyitem";
private List<NotifyRequestsStatus> notifyStatus;
private List<RequestStatus> notifyStatus;
private UUID itemuuid;
public NotifyRequestStatusRest(NotifyRequestStatusRest instance) {
this.notifyStatus = instance.getNotifyStatus();
}
public NotifyRequestStatusRest() {
super();
this.notifyStatus = new ArrayList<RequestStatus>();
}
public UUID getItemuuid() {
@@ -55,17 +62,15 @@ public class NotifyRequestStatusRest extends RestAddressableModel {
}
public Class getController() {
return RestResourceController.class;
return NotifyRequestStatusRestController.class;
}
public List<RequestStatus> getNotifyStatus() {
return notifyStatus;
}
public void setNotifyStatus(List<RequestStatus> notifyStatus) {
this.notifyStatus = notifyStatus;
}
}
enum NotifyStatus {
REJECTED, ACCEPTED, REQUESTED
}
class NotifyRequestsStatus {
String serviceName;
String serviceUrl;
NotifyStatus status;
}

View File

@@ -0,0 +1,25 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.model.hateoas;
import org.dspace.app.rest.model.NotifyRequestStatusRest;
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
import org.dspace.app.rest.utils.Utils;
/**
* NotifyRequestStatus Rest HAL Resource. The HAL Resource wraps the REST Resource
* adding support for the links and embedded resources
*
* @author Francesco Bacchelli (francesco.bacchelli at 4science.it)
*/
@RelNameDSpaceResource(NotifyRequestStatusRest.NAME)
public class NotifyRequestStatusResource extends DSpaceResource<NotifyRequestStatusRest> {
public NotifyRequestStatusResource(NotifyRequestStatusRest status, Utils utils) {
super(status, utils);
}
}

View File

@@ -57,7 +57,7 @@
<entry>
<key>
<set>
<value>Reject</value>
<value>TentativeReject</value>
<value>coar-notify:ReviewAction</value>
</set>
</key>
@@ -72,10 +72,70 @@
</key>
<ref bean="announceReleaseAction" />
</entry>
<entry>
<key>
<set>
<value>Offer</value>
<value>coar-notify:ReviewAction</value>
</set>
</key>
<ref bean="offerReviewAction" />
</entry>
<entry>
<key>
<set>
<value>Offer</value>
<value>coar-notify:IngestAction</value>
</set>
</key>
<ref bean="offerIngestAction" />
</entry>
<entry>
<key>
<set>
<value>Offer</value>
<value>coar-notify:EndorsementAction</value>
</set>
</key>
<ref bean="offerEndorsementAction" />
</entry>
</map>
</property>
</bean>
<bean name="offerEndorsementAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
<property name="actions">
<list value-type="org.dspace.app.ldn.action.LDNAction">
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
<property name="actionSendFilter" value="william_welling@harvard.edu" />
<property name="actionSendEmailTextFile" value="coar_notify_reviewed" />
</bean>
</list>
</property>
</bean>
<bean name="offerIngestAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
<property name="actions">
<list value-type="org.dspace.app.ldn.action.LDNAction">
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
<property name="actionSendFilter" value="william_welling@harvard.edu" />
<property name="actionSendEmailTextFile" value="coar_notify_reviewed" />
</bean>
</list>
</property>
</bean>
<bean name="offerReviewAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
<property name="actions">
<list value-type="org.dspace.app.ldn.action.LDNAction">
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
<property name="actionSendFilter" value="william_welling@harvard.edu" />
<property name="actionSendEmailTextFile" value="coar_notify_reviewed" />
</bean>
</list>
</property>
</bean>
<bean name="announceReviewAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
<property name="actions">
<list value-type="org.dspace.app.ldn.action.LDNAction">