mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-16 14:33:09 +00:00
Merge conflicts to coar-notify-7
This commit is contained in:
@@ -1,190 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.app.ldn;
|
|
||||||
|
|
||||||
import static java.lang.String.format;
|
|
||||||
import static java.lang.String.join;
|
|
||||||
import static org.dspace.app.ldn.RdfMediaType.APPLICATION_JSON_LD;
|
|
||||||
import static org.dspace.app.ldn.utility.LDNUtils.processContextResolverId;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.dspace.app.ldn.converter.JsonLdHttpMessageConverter;
|
|
||||||
import org.dspace.app.ldn.model.Actor;
|
|
||||||
import org.dspace.app.ldn.model.Context;
|
|
||||||
import org.dspace.app.ldn.model.Notification;
|
|
||||||
import org.dspace.app.ldn.model.Object;
|
|
||||||
import org.dspace.app.ldn.model.Service;
|
|
||||||
import org.dspace.content.Item;
|
|
||||||
import org.dspace.content.MetadataField;
|
|
||||||
import org.dspace.content.MetadataValue;
|
|
||||||
import org.dspace.handle.service.HandleService;
|
|
||||||
import org.dspace.services.ConfigurationService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.HttpEntity;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Linked Data Notification business delegate to facilitate sending
|
|
||||||
* notification.
|
|
||||||
*/
|
|
||||||
public class LDNBusinessDelegate {
|
|
||||||
|
|
||||||
private final static Logger log = LogManager.getLogger(LDNBusinessDelegate.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ConfigurationService configurationService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private HandleService handleService;
|
|
||||||
|
|
||||||
private final RestTemplate restTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize rest template with appropriate message converters.
|
|
||||||
*/
|
|
||||||
public LDNBusinessDelegate() {
|
|
||||||
restTemplate = new RestTemplate();
|
|
||||||
restTemplate.getMessageConverters().add(new JsonLdHttpMessageConverter());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Announce item release notification.
|
|
||||||
*
|
|
||||||
* @param item item released (deposited or updated)
|
|
||||||
* @throws SQLException
|
|
||||||
*/
|
|
||||||
public void announceRelease(Item item) {
|
|
||||||
String serviceIds = configurationService.getProperty("service.service-id.ldn");
|
|
||||||
|
|
||||||
for (String serviceId : serviceIds.split(",")) {
|
|
||||||
doAnnounceRelease(item, serviceId.trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build and POST announce release notification to configured service LDN
|
|
||||||
* inboxes.
|
|
||||||
*
|
|
||||||
* @param item associated item
|
|
||||||
* @param serviceId service id for targer inbox
|
|
||||||
*/
|
|
||||||
public void doAnnounceRelease(Item item, String serviceId) {
|
|
||||||
log.info("Announcing release of item {}", item.getID());
|
|
||||||
|
|
||||||
String dspaceServerUrl = configurationService.getProperty("dspace.server.url");
|
|
||||||
String dspaceUIUrl = configurationService.getProperty("dspace.ui.url");
|
|
||||||
String dspaceName = configurationService.getProperty("dspace.name");
|
|
||||||
String dspaceLdnInboxUrl = configurationService.getProperty("ldn.notify.inbox");
|
|
||||||
|
|
||||||
log.info("DSpace Server URL {}", dspaceServerUrl);
|
|
||||||
log.info("DSpace UI URL {}", dspaceUIUrl);
|
|
||||||
log.info("DSpace Name {}", dspaceName);
|
|
||||||
log.info("DSpace LDN Inbox URL {}", dspaceLdnInboxUrl);
|
|
||||||
|
|
||||||
String serviceUrl = configurationService.getProperty(join(".", "service", serviceId, "url"));
|
|
||||||
String serviceInboxUrl = configurationService.getProperty(join(".", "service", serviceId, "inbox.url"));
|
|
||||||
String serviceResolverUrl = configurationService.getProperty(join(".", "service", serviceId, "resolver.url"));
|
|
||||||
|
|
||||||
log.info("Target URL {}", serviceUrl);
|
|
||||||
log.info("Target LDN Inbox URL {}", serviceInboxUrl);
|
|
||||||
|
|
||||||
Notification notification = new Notification();
|
|
||||||
|
|
||||||
notification.setId(format("urn:uuid:%s", UUID.randomUUID()));
|
|
||||||
notification.addType("Announce");
|
|
||||||
notification.addType("coar-notify:ReleaseAction");
|
|
||||||
|
|
||||||
Actor actor = new Actor();
|
|
||||||
|
|
||||||
actor.setId(dspaceUIUrl);
|
|
||||||
actor.setName(dspaceName);
|
|
||||||
actor.addType("Service");
|
|
||||||
|
|
||||||
Context context = new Context();
|
|
||||||
|
|
||||||
List<Context> isSupplementedBy = new ArrayList<>();
|
|
||||||
|
|
||||||
List<MetadataValue> metadata = item.getMetadata();
|
|
||||||
for (MetadataValue metadatum : metadata) {
|
|
||||||
MetadataField field = metadatum.getMetadataField();
|
|
||||||
log.info("Metadata field {} with value {}", field, metadatum.getValue());
|
|
||||||
if (field.getMetadataSchema().getName().equals("dc") &&
|
|
||||||
field.getElement().equals("data") &&
|
|
||||||
field.getQualifier().equals("uri")) {
|
|
||||||
|
|
||||||
String ietfCiteAs = metadatum.getValue();
|
|
||||||
String resolverId = processContextResolverId(ietfCiteAs);
|
|
||||||
String id = serviceResolverUrl != null
|
|
||||||
? format("%s%s", serviceResolverUrl, resolverId)
|
|
||||||
: ietfCiteAs;
|
|
||||||
|
|
||||||
Context supplement = new Context();
|
|
||||||
supplement.setId(id);
|
|
||||||
supplement.setIetfCiteAs(ietfCiteAs);
|
|
||||||
supplement.addType("sorg:Dataset");
|
|
||||||
|
|
||||||
isSupplementedBy.add(supplement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.setIsSupplementedBy(isSupplementedBy);
|
|
||||||
|
|
||||||
Object object = new Object();
|
|
||||||
|
|
||||||
String itemUrl = handleService.getCanonicalForm(item.getHandle());
|
|
||||||
|
|
||||||
log.info("Item Handle URL {}", itemUrl);
|
|
||||||
|
|
||||||
log.info("Item URL {}", itemUrl);
|
|
||||||
|
|
||||||
object.setId(itemUrl);
|
|
||||||
object.setIetfCiteAs(itemUrl);
|
|
||||||
object.setTitle(item.getName());
|
|
||||||
object.addType("sorg:ScholarlyArticle");
|
|
||||||
|
|
||||||
Service origin = new Service();
|
|
||||||
origin.setId(dspaceUIUrl);
|
|
||||||
origin.setInbox(dspaceLdnInboxUrl);
|
|
||||||
origin.addType("Service");
|
|
||||||
|
|
||||||
Service target = new Service();
|
|
||||||
target.setId(serviceUrl);
|
|
||||||
target.setInbox(serviceInboxUrl);
|
|
||||||
target.addType("Service");
|
|
||||||
|
|
||||||
notification.setActor(actor);
|
|
||||||
notification.setContext(context);
|
|
||||||
notification.setObject(object);
|
|
||||||
notification.setOrigin(origin);
|
|
||||||
notification.setTarget(target);
|
|
||||||
|
|
||||||
String serviceKey = configurationService.getProperty(join(".", "service", serviceId, "key"));
|
|
||||||
String serviceKeyHeader = configurationService.getProperty(join(".", "service", serviceId, "key.header"));
|
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add("Content-Type", APPLICATION_JSON_LD.toString());
|
|
||||||
if (serviceKey != null && serviceKeyHeader != null) {
|
|
||||||
headers.add(serviceKeyHeader, serviceKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpEntity<Notification> request = new HttpEntity<Notification>(notification, headers);
|
|
||||||
|
|
||||||
log.info("Announcing notification {}", request);
|
|
||||||
|
|
||||||
restTemplate.postForLocation(URI.create(target.getInbox()), request);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,209 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import static java.lang.String.format;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.app.ldn.factory.NotifyServiceFactory;
|
||||||
|
import org.dspace.app.ldn.model.Notification;
|
||||||
|
import org.dspace.app.ldn.service.LDNMessageService;
|
||||||
|
import org.dspace.app.ldn.service.NotifyPatternToTriggerService;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.BitstreamFormat;
|
||||||
|
import org.dspace.content.Bundle;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.MetadataValue;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.BitstreamService;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.core.I18nUtil;
|
||||||
|
import org.dspace.core.LDN;
|
||||||
|
import org.dspace.event.Consumer;
|
||||||
|
import org.dspace.event.Event;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.web.ContextUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class for creating a new LDN Messages of installed item
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.com)
|
||||||
|
*/
|
||||||
|
public class LDNMessageConsumer implements Consumer {
|
||||||
|
|
||||||
|
private NotifyPatternToTriggerService notifyPatternToTriggerService;
|
||||||
|
private LDNMessageService ldnMessageService;
|
||||||
|
private ConfigurationService configurationService;
|
||||||
|
private ItemService itemService;
|
||||||
|
private BitstreamService bitstreamService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() throws Exception {
|
||||||
|
notifyPatternToTriggerService = NotifyServiceFactory.getInstance().getNotifyPatternToTriggerService();
|
||||||
|
ldnMessageService = NotifyServiceFactory.getInstance().getLDNMessageService();
|
||||||
|
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void consume(Context context, Event event) throws Exception {
|
||||||
|
|
||||||
|
if (event.getSubjectType() != Constants.ITEM ||
|
||||||
|
event.getEventType() != Event.INSTALL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
createLDNMessages(context, (Item) event.getSubject(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLDNMessages(Context context, Item item) throws SQLException {
|
||||||
|
List<NotifyPatternToTrigger> patternsToTrigger =
|
||||||
|
notifyPatternToTriggerService.findByItem(context, item);
|
||||||
|
|
||||||
|
patternsToTrigger.forEach(patternToTrigger -> {
|
||||||
|
try {
|
||||||
|
createLDNMessage(context, patternToTrigger);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLDNMessage(Context context, NotifyPatternToTrigger patternToTrigger)
|
||||||
|
throws SQLException, JsonMappingException, JsonProcessingException {
|
||||||
|
|
||||||
|
LDN ldn = getLDNMessage(patternToTrigger.getPattern());
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.create(context, format("urn:uuid:%s", UUID.randomUUID()));
|
||||||
|
|
||||||
|
ldnMessage.setObject(patternToTrigger.getItem());
|
||||||
|
ldnMessage.setTarget(patternToTrigger.getNotifyService());
|
||||||
|
ldnMessage.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_QUEUED);
|
||||||
|
ldnMessage.setQueueTimeout(new Date());
|
||||||
|
|
||||||
|
appendGeneratedMessage(ldn, ldnMessage, patternToTrigger.getPattern());
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
Notification notification = mapper.readValue(ldnMessage.getMessage(), Notification.class);
|
||||||
|
ldnMessage.setType(StringUtils.joinWith(",", notification.getType()));
|
||||||
|
|
||||||
|
ArrayList<String> notificationTypeArrayList = new ArrayList<String>(notification.getType());
|
||||||
|
// sorting the list
|
||||||
|
Collections.sort(notificationTypeArrayList);
|
||||||
|
ldnMessage.setActivityStreamType(notificationTypeArrayList.get(0));
|
||||||
|
ldnMessage.setCoarNotifyType(notificationTypeArrayList.get(1));
|
||||||
|
|
||||||
|
ldnMessageService.update(context, ldnMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LDN getLDNMessage(String pattern) {
|
||||||
|
try {
|
||||||
|
return LDN.getLDNMessage(I18nUtil.getLDNFilename(Locale.getDefault(), pattern));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendGeneratedMessage(LDN ldn, LDNMessageEntity ldnMessage, String pattern) {
|
||||||
|
Item item = (Item) ldnMessage.getObject();
|
||||||
|
ldn.addArgument(getUiUrl());
|
||||||
|
ldn.addArgument(configurationService.getProperty("ldn.notify.inbox"));
|
||||||
|
ldn.addArgument(configurationService.getProperty("dspace.name"));
|
||||||
|
ldn.addArgument(Objects.requireNonNullElse(ldnMessage.getTarget().getUrl(), ""));
|
||||||
|
ldn.addArgument(Objects.requireNonNullElse(ldnMessage.getTarget().getLdnUrl(), ""));
|
||||||
|
ldn.addArgument(getUiUrl() + "/handle/" + ldnMessage.getObject().getHandle());
|
||||||
|
ldn.addArgument(getIdentifierUri(item));
|
||||||
|
ldn.addArgument(generateBitstreamDownloadUrl(item));
|
||||||
|
ldn.addArgument(getBitstreamMimeType(findPrimaryBitstream(item)));
|
||||||
|
ldn.addArgument(ldnMessage.getID());
|
||||||
|
|
||||||
|
ldnMessage.setMessage(ldn.generateLDNMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUiUrl() {
|
||||||
|
return configurationService.getProperty("dspace.ui.url");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getIdentifierUri(Item item) {
|
||||||
|
return itemService.getMetadataByMetadataString(item, "dc.identifier.uri")
|
||||||
|
.stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(MetadataValue::getValue)
|
||||||
|
.orElse("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateBitstreamDownloadUrl(Item item) {
|
||||||
|
String uiUrl = getUiUrl();
|
||||||
|
return findPrimaryBitstream(item)
|
||||||
|
.map(bs -> uiUrl + "/bitstreams/" + bs.getID() + "/download")
|
||||||
|
.orElse("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Bitstream> findPrimaryBitstream(Item item) {
|
||||||
|
List<Bundle> bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME);
|
||||||
|
return bundles.stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(Bundle::getPrimaryBitstream)
|
||||||
|
.or(() -> bundles.stream()
|
||||||
|
.findFirst()
|
||||||
|
.flatMap(bundle -> CollectionUtils.isNotEmpty(bundle.getBitstreams())
|
||||||
|
? Optional.of(bundle.getBitstreams().get(0))
|
||||||
|
: Optional.empty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getBitstreamMimeType(Optional<Bitstream> bitstream) {
|
||||||
|
return bitstream.map(bs -> {
|
||||||
|
try {
|
||||||
|
Context context = ContextUtil.obtainCurrentRequestContext();
|
||||||
|
BitstreamFormat bitstreamFormat = bs.getFormat(context);
|
||||||
|
if (bitstreamFormat.getShortDescription().equals("Unknown")) {
|
||||||
|
return getUserFormatMimeType(bs);
|
||||||
|
}
|
||||||
|
return bitstreamFormat.getMIMEType();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}).orElse("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUserFormatMimeType(Bitstream bitstream) {
|
||||||
|
return bitstreamService.getMetadataFirstValue(bitstream,
|
||||||
|
"dc", "format", "mimetype", Item.ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void end(Context ctx) throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish(Context ctx) throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -21,7 +21,8 @@ import org.dspace.app.ldn.processor.LDNProcessor;
|
|||||||
*/
|
*/
|
||||||
public class LDNRouter {
|
public class LDNRouter {
|
||||||
|
|
||||||
private Map<Set<String>, LDNProcessor> processors = new HashMap<>();
|
private Map<Set<String>, LDNProcessor> incomingProcessors = new HashMap<>();
|
||||||
|
private Map<Set<String>, LDNProcessor> outcomingProcessors = new HashMap<>();
|
||||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(LDNRouter.class);
|
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(LDNRouter.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,26 +42,50 @@ public class LDNRouter {
|
|||||||
Set<String> ldnMessageTypeSet = new HashSet<String>();
|
Set<String> ldnMessageTypeSet = new HashSet<String>();
|
||||||
ldnMessageTypeSet.add(ldnMessage.getActivityStreamType());
|
ldnMessageTypeSet.add(ldnMessage.getActivityStreamType());
|
||||||
ldnMessageTypeSet.add(ldnMessage.getCoarNotifyType());
|
ldnMessageTypeSet.add(ldnMessage.getCoarNotifyType());
|
||||||
LDNProcessor processor = processors.get(ldnMessageTypeSet);
|
|
||||||
|
LDNProcessor processor = null;
|
||||||
|
if (ldnMessage.getTarget() == null) {
|
||||||
|
processor = incomingProcessors.get(ldnMessageTypeSet);
|
||||||
|
} else if (ldnMessage.getOrigin() == null) {
|
||||||
|
processor = outcomingProcessors.get(ldnMessageTypeSet);
|
||||||
|
}
|
||||||
|
|
||||||
return processor;
|
return processor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all routes.
|
* Get all incoming routes.
|
||||||
*
|
*
|
||||||
* @return Map<Set<String>, LDNProcessor>
|
* @return Map<Set<String>, LDNProcessor>
|
||||||
*/
|
*/
|
||||||
public Map<Set<String>, LDNProcessor> getProcessors() {
|
public Map<Set<String>, LDNProcessor> getIncomingProcessors() {
|
||||||
return processors;
|
return incomingProcessors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set all routes.
|
* Set all incoming routes.
|
||||||
*
|
*
|
||||||
* @param processors
|
* @param incomingProcessors
|
||||||
*/
|
*/
|
||||||
public void setProcessors(Map<Set<String>, LDNProcessor> processors) {
|
public void setIncomingProcessors(Map<Set<String>, LDNProcessor> incomingProcessors) {
|
||||||
this.processors = processors;
|
this.incomingProcessors = incomingProcessors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all outcoming routes.
|
||||||
|
*
|
||||||
|
* @return Map<Set<String>, LDNProcessor>
|
||||||
|
*/
|
||||||
|
public Map<Set<String>, LDNProcessor> getOutcomingProcessors() {
|
||||||
|
return outcomingProcessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all outcoming routes.
|
||||||
|
*
|
||||||
|
* @param outcomingProcessors
|
||||||
|
*/
|
||||||
|
public void setOutcomingProcessors(Map<Set<String>, LDNProcessor> outcomingProcessors) {
|
||||||
|
this.outcomingProcessors = outcomingProcessors;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
* 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.action;
|
||||||
|
|
||||||
|
import static org.dspace.app.ldn.RdfMediaType.APPLICATION_JSON_LD;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.app.ldn.converter.JsonLdHttpMessageConverter;
|
||||||
|
import org.dspace.app.ldn.model.Notification;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.http.HttpEntity;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action to send LDN Message
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.com)
|
||||||
|
*/
|
||||||
|
public class SendLDNMessageAction implements LDNAction {
|
||||||
|
|
||||||
|
private static final Logger log = LogManager.getLogger(SendLDNMessageAction.class);
|
||||||
|
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
public SendLDNMessageAction() {
|
||||||
|
restTemplate = new RestTemplate();
|
||||||
|
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||||
|
messageConverters.add(new JsonLdHttpMessageConverter());
|
||||||
|
messageConverters.addAll(restTemplate.getMessageConverters());
|
||||||
|
restTemplate.setMessageConverters(messageConverters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionStatus execute(Context context, Notification notification, Item item) throws Exception {
|
||||||
|
//TODO authorization with Bearer token should be supported.
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.add("Content-Type", APPLICATION_JSON_LD.toString());
|
||||||
|
|
||||||
|
HttpEntity<Notification> request = new HttpEntity<>(notification, headers);
|
||||||
|
|
||||||
|
log.info("Announcing notification {}", request);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResponseEntity<String> response = restTemplate.postForEntity(
|
||||||
|
notification.getTarget().getInbox(),
|
||||||
|
request,
|
||||||
|
String.class);
|
||||||
|
|
||||||
|
if (isSuccessful(response.getStatusCode())) {
|
||||||
|
return ActionStatus.CONTINUE;
|
||||||
|
} else if (isRedirect(response.getStatusCode())) {
|
||||||
|
return handleRedirect(response, request);
|
||||||
|
} else {
|
||||||
|
return ActionStatus.ABORT;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e);
|
||||||
|
return ActionStatus.ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSuccessful(HttpStatus statusCode) {
|
||||||
|
return statusCode == HttpStatus.ACCEPTED ||
|
||||||
|
statusCode == HttpStatus.CREATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRedirect(HttpStatus statusCode) {
|
||||||
|
return statusCode == HttpStatus.PERMANENT_REDIRECT ||
|
||||||
|
statusCode == HttpStatus.TEMPORARY_REDIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionStatus handleRedirect(ResponseEntity<String> response,
|
||||||
|
HttpEntity<Notification> request) {
|
||||||
|
|
||||||
|
String url = response.getHeaders().getFirst(HttpHeaders.LOCATION);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResponseEntity<String> responseEntity =
|
||||||
|
restTemplate.postForEntity(url, request, String.class);
|
||||||
|
|
||||||
|
if (isSuccessful(responseEntity.getStatusCode())) {
|
||||||
|
return ActionStatus.CONTINUE;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error following redirect:", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionStatus.ABORT;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,37 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.app.ldn.factory;
|
|
||||||
|
|
||||||
import org.dspace.app.ldn.LDNBusinessDelegate;
|
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract business delegate factory to provide ability to get instance from
|
|
||||||
* dspace services factory.
|
|
||||||
*/
|
|
||||||
public abstract class LDNBusinessDelegateFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract method to return the business delegate bean.
|
|
||||||
*
|
|
||||||
* @return LDNBusinessDelegate business delegate bean
|
|
||||||
*/
|
|
||||||
public abstract LDNBusinessDelegate getLDNBusinessDelegate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static method to get the business delegate factory instance.
|
|
||||||
*
|
|
||||||
* @return LDNBusinessDelegateFactory business delegate factory from dspace
|
|
||||||
* services factory
|
|
||||||
*/
|
|
||||||
public static LDNBusinessDelegateFactory getInstance() {
|
|
||||||
return DSpaceServicesFactory.getInstance().getServiceManager()
|
|
||||||
.getServiceByName("ldnBusinessDelegateFactory", LDNBusinessDelegateFactory.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,30 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.app.ldn.factory;
|
|
||||||
|
|
||||||
import org.dspace.app.ldn.LDNBusinessDelegate;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business delegate factory implementation that autowires business delegate for
|
|
||||||
* static retrieval.
|
|
||||||
*/
|
|
||||||
public class LDNBusinessDelegateFactoryImpl extends LDNBusinessDelegateFactory {
|
|
||||||
|
|
||||||
@Autowired(required = true)
|
|
||||||
private LDNBusinessDelegate ldnBusinessDelegate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return LDNBusinessDelegate
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public LDNBusinessDelegate getLDNBusinessDelegate() {
|
|
||||||
return ldnBusinessDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.ldn.factory;
|
package org.dspace.app.ldn.factory;
|
||||||
|
|
||||||
|
import org.dspace.app.ldn.service.LDNMessageService;
|
||||||
import org.dspace.app.ldn.service.NotifyPatternToTriggerService;
|
import org.dspace.app.ldn.service.NotifyPatternToTriggerService;
|
||||||
import org.dspace.app.ldn.service.NotifyService;
|
import org.dspace.app.ldn.service.NotifyService;
|
||||||
import org.dspace.app.ldn.service.NotifyServiceInboundPatternService;
|
import org.dspace.app.ldn.service.NotifyServiceInboundPatternService;
|
||||||
@@ -26,6 +27,8 @@ public abstract class NotifyServiceFactory {
|
|||||||
|
|
||||||
public abstract NotifyPatternToTriggerService getNotifyPatternToTriggerService();
|
public abstract NotifyPatternToTriggerService getNotifyPatternToTriggerService();
|
||||||
|
|
||||||
|
public abstract LDNMessageService getLDNMessageService();
|
||||||
|
|
||||||
public static NotifyServiceFactory getInstance() {
|
public static NotifyServiceFactory getInstance() {
|
||||||
return DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
|
return DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(
|
||||||
"notifyServiceFactory", NotifyServiceFactory.class);
|
"notifyServiceFactory", NotifyServiceFactory.class);
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.ldn.factory;
|
package org.dspace.app.ldn.factory;
|
||||||
|
|
||||||
|
import org.dspace.app.ldn.service.LDNMessageService;
|
||||||
import org.dspace.app.ldn.service.NotifyPatternToTriggerService;
|
import org.dspace.app.ldn.service.NotifyPatternToTriggerService;
|
||||||
import org.dspace.app.ldn.service.NotifyService;
|
import org.dspace.app.ldn.service.NotifyService;
|
||||||
import org.dspace.app.ldn.service.NotifyServiceInboundPatternService;
|
import org.dspace.app.ldn.service.NotifyServiceInboundPatternService;
|
||||||
@@ -29,6 +30,9 @@ public class NotifyServiceFactoryImpl extends NotifyServiceFactory {
|
|||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
private NotifyPatternToTriggerService notifyPatternToTriggerService;
|
private NotifyPatternToTriggerService notifyPatternToTriggerService;
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
private LDNMessageService ldnMessageService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NotifyService getNotifyService() {
|
public NotifyService getNotifyService() {
|
||||||
return notifyService;
|
return notifyService;
|
||||||
@@ -44,4 +48,9 @@ public class NotifyServiceFactoryImpl extends NotifyServiceFactory {
|
|||||||
return notifyPatternToTriggerService;
|
return notifyPatternToTriggerService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LDNMessageService getLDNMessageService() {
|
||||||
|
return ldnMessageService;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,48 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.app.ldn.processor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instuctions for adding metadata during notification processing.
|
|
||||||
*/
|
|
||||||
public class LDNMetadataAdd extends LDNMetadataChange {
|
|
||||||
|
|
||||||
private String qualifier;
|
|
||||||
|
|
||||||
// velocity template with notification as it contexts
|
|
||||||
private String valueTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getQualifier() {
|
|
||||||
return qualifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param qualifier
|
|
||||||
*/
|
|
||||||
public void setQualifier(String qualifier) {
|
|
||||||
this.qualifier = qualifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getValueTemplate() {
|
|
||||||
return valueTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param valueTemplate
|
|
||||||
*/
|
|
||||||
public void setValueTemplate(String valueTemplate) {
|
|
||||||
this.valueTemplate = valueTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,95 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.app.ldn.processor;
|
|
||||||
|
|
||||||
import static org.dspace.app.ldn.LDNMetadataFields.ELEMENT;
|
|
||||||
import static org.dspace.app.ldn.LDNMetadataFields.SCHEMA;
|
|
||||||
import static org.dspace.content.Item.ANY;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base instructions for metadata change during notification processing.
|
|
||||||
*/
|
|
||||||
public abstract class LDNMetadataChange {
|
|
||||||
|
|
||||||
private String schema;
|
|
||||||
|
|
||||||
private String element;
|
|
||||||
|
|
||||||
private String language;
|
|
||||||
|
|
||||||
// velocity template with notification as its context
|
|
||||||
private String conditionTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default coar schema, notify element, any language, and true condition to
|
|
||||||
* apply metadata change.
|
|
||||||
*/
|
|
||||||
public LDNMetadataChange() {
|
|
||||||
schema = SCHEMA;
|
|
||||||
element = ELEMENT;
|
|
||||||
language = ANY;
|
|
||||||
conditionTemplate = "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getSchema() {
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param schema
|
|
||||||
*/
|
|
||||||
public void setSchema(String schema) {
|
|
||||||
this.schema = schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getElement() {
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param element
|
|
||||||
*/
|
|
||||||
public void setElement(String element) {
|
|
||||||
this.element = element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getLanguage() {
|
|
||||||
return language;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param language
|
|
||||||
*/
|
|
||||||
public void setLanguage(String language) {
|
|
||||||
this.language = language;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String getConditionTemplate() {
|
|
||||||
return conditionTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param conditionTemplate
|
|
||||||
*/
|
|
||||||
public void setConditionTemplate(String conditionTemplate) {
|
|
||||||
this.conditionTemplate = conditionTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -9,30 +9,20 @@ package org.dspace.app.ldn.processor;
|
|||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.velocity.VelocityContext;
|
|
||||||
import org.apache.velocity.app.Velocity;
|
|
||||||
import org.apache.velocity.app.VelocityEngine;
|
|
||||||
import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
|
|
||||||
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
|
|
||||||
import org.dspace.app.ldn.action.ActionStatus;
|
import org.dspace.app.ldn.action.ActionStatus;
|
||||||
import org.dspace.app.ldn.action.LDNAction;
|
import org.dspace.app.ldn.action.LDNAction;
|
||||||
import org.dspace.app.ldn.model.Notification;
|
import org.dspace.app.ldn.model.Notification;
|
||||||
import org.dspace.app.ldn.utility.LDNUtils;
|
import org.dspace.app.ldn.utility.LDNUtils;
|
||||||
import org.dspace.content.DSpaceObject;
|
import org.dspace.content.DSpaceObject;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.content.MetadataValue;
|
|
||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
@@ -49,10 +39,6 @@ public class LDNMetadataProcessor implements LDNProcessor {
|
|||||||
|
|
||||||
private final static Logger log = LogManager.getLogger(LDNMetadataProcessor.class);
|
private final static Logger log = LogManager.getLogger(LDNMetadataProcessor.class);
|
||||||
|
|
||||||
private final static String DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
|
|
||||||
|
|
||||||
private final VelocityEngine velocityEngine;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ItemService itemService;
|
private ItemService itemService;
|
||||||
|
|
||||||
@@ -63,16 +49,11 @@ public class LDNMetadataProcessor implements LDNProcessor {
|
|||||||
|
|
||||||
private List<LDNAction> actions = new ArrayList<>();
|
private List<LDNAction> actions = new ArrayList<>();
|
||||||
|
|
||||||
private List<LDNMetadataChange> changes = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize velocity engine for templating.
|
* Initialize velocity engine for templating.
|
||||||
*/
|
*/
|
||||||
private LDNMetadataProcessor() {
|
private LDNMetadataProcessor() {
|
||||||
velocityEngine = new VelocityEngine();
|
|
||||||
velocityEngine.setProperty(Velocity.RESOURCE_LOADERS, "string");
|
|
||||||
velocityEngine.setProperty("resource.loader.string.class", StringResourceLoader.class.getName());
|
|
||||||
velocityEngine.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,106 +65,8 @@ public class LDNMetadataProcessor implements LDNProcessor {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void process(Context context, Notification notification) throws Exception {
|
public void process(Context context, Notification notification) throws Exception {
|
||||||
Item item = doProcess(context, notification);
|
|
||||||
runActions(context, notification, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform the actual notification processing. Applies all defined metadata
|
|
||||||
* changes.
|
|
||||||
*
|
|
||||||
* @param context the current context
|
|
||||||
* @param notification current context notification
|
|
||||||
* @return Item associated item which persist notification details
|
|
||||||
* @throws Exception failed to process notification
|
|
||||||
*/
|
|
||||||
private Item doProcess(Context context, Notification notification) throws Exception {
|
|
||||||
log.info("Processing notification {} {}", notification.getId(), notification.getType());
|
|
||||||
boolean updated = false;
|
|
||||||
VelocityContext velocityContext = prepareTemplateContext(notification);
|
|
||||||
|
|
||||||
Item item = lookupItem(context, notification);
|
Item item = lookupItem(context, notification);
|
||||||
|
runActions(context, notification, item);
|
||||||
List<MetadataValue> metadataValuesToRemove = new ArrayList<>();
|
|
||||||
|
|
||||||
for (LDNMetadataChange change : changes) {
|
|
||||||
String condition = renderTemplate(velocityContext, change.getConditionTemplate());
|
|
||||||
|
|
||||||
boolean proceed = Boolean.parseBoolean(condition);
|
|
||||||
|
|
||||||
if (!proceed) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (change instanceof LDNMetadataAdd) {
|
|
||||||
LDNMetadataAdd add = ((LDNMetadataAdd) change);
|
|
||||||
String value = renderTemplate(velocityContext, add.getValueTemplate());
|
|
||||||
log.info(
|
|
||||||
"Adding {}.{}.{} {} {}",
|
|
||||||
add.getSchema(),
|
|
||||||
add.getElement(),
|
|
||||||
add.getQualifier(),
|
|
||||||
add.getLanguage(),
|
|
||||||
value);
|
|
||||||
itemService.addMetadata(
|
|
||||||
context,
|
|
||||||
item,
|
|
||||||
add.getSchema(),
|
|
||||||
add.getElement(),
|
|
||||||
add.getQualifier(),
|
|
||||||
add.getLanguage(),
|
|
||||||
value);
|
|
||||||
updated = true;
|
|
||||||
} else if (change instanceof LDNMetadataRemove) {
|
|
||||||
LDNMetadataRemove remove = (LDNMetadataRemove) change;
|
|
||||||
|
|
||||||
for (String qualifier : remove.getQualifiers()) {
|
|
||||||
List<MetadataValue> itemMetadata = itemService.getMetadata(
|
|
||||||
item,
|
|
||||||
change.getSchema(),
|
|
||||||
change.getElement(),
|
|
||||||
qualifier,
|
|
||||||
Item.ANY);
|
|
||||||
|
|
||||||
for (MetadataValue metadatum : itemMetadata) {
|
|
||||||
boolean delete = true;
|
|
||||||
for (String valueTemplate : remove.getValueTemplates()) {
|
|
||||||
String value = renderTemplate(velocityContext, valueTemplate);
|
|
||||||
if (!metadatum.getValue().contains(value)) {
|
|
||||||
delete = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (delete) {
|
|
||||||
log.info("Removing {}.{}.{} {} {}",
|
|
||||||
remove.getSchema(),
|
|
||||||
remove.getElement(),
|
|
||||||
qualifier,
|
|
||||||
remove.getLanguage(),
|
|
||||||
metadatum.getValue());
|
|
||||||
|
|
||||||
metadataValuesToRemove.add(metadatum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!metadataValuesToRemove.isEmpty()) {
|
|
||||||
itemService.removeMetadataValues(context, item, metadataValuesToRemove);
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updated) {
|
|
||||||
context.turnOffAuthorisationSystem();
|
|
||||||
try {
|
|
||||||
itemService.update(context, item);
|
|
||||||
context.commit();
|
|
||||||
} finally {
|
|
||||||
context.restoreAuthSystemState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -241,20 +124,6 @@ public class LDNMetadataProcessor implements LDNProcessor {
|
|||||||
this.actions = actions;
|
this.actions = actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return List<LDNMetadataChange>
|
|
||||||
*/
|
|
||||||
public List<LDNMetadataChange> getChanges() {
|
|
||||||
return changes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param changes
|
|
||||||
*/
|
|
||||||
public void setChanges(List<LDNMetadataChange> changes) {
|
|
||||||
this.changes = changes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup associated item to the notification context. If UUID in URL, lookup bu
|
* Lookup associated item to the notification context. If UUID in URL, lookup bu
|
||||||
* UUID, else lookup by handle.
|
* UUID, else lookup by handle.
|
||||||
@@ -312,41 +181,4 @@ public class LDNMetadataProcessor implements LDNProcessor {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare velocity template context with notification, timestamp and some
|
|
||||||
* static utilities.
|
|
||||||
*
|
|
||||||
* @param notification current context notification
|
|
||||||
* @return VelocityContext prepared velocity context
|
|
||||||
*/
|
|
||||||
private VelocityContext prepareTemplateContext(Notification notification) {
|
|
||||||
VelocityContext velocityContext = new VelocityContext();
|
|
||||||
|
|
||||||
String timestamp = new SimpleDateFormat(DATE_PATTERN).format(Calendar.getInstance().getTime());
|
|
||||||
|
|
||||||
velocityContext.put("notification", notification);
|
|
||||||
velocityContext.put("timestamp", timestamp);
|
|
||||||
velocityContext.put("LDNUtils", LDNUtils.class);
|
|
||||||
velocityContext.put("Objects", Objects.class);
|
|
||||||
velocityContext.put("StringUtils", StringUtils.class);
|
|
||||||
|
|
||||||
return velocityContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render velocity template with provided context.
|
|
||||||
*
|
|
||||||
* @param context velocity context
|
|
||||||
* @param template template to render
|
|
||||||
* @return String results of rendering
|
|
||||||
*/
|
|
||||||
private String renderTemplate(VelocityContext context, String template) {
|
|
||||||
StringWriter writer = new StringWriter();
|
|
||||||
StringResourceRepository repository = StringResourceLoader.getRepository();
|
|
||||||
repository.putStringResource("template", template);
|
|
||||||
velocityEngine.getTemplate("template").merge(context, writer);
|
|
||||||
|
|
||||||
return writer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@@ -1,51 +0,0 @@
|
|||||||
/**
|
|
||||||
* The contents of this file are subject to the license and copyright
|
|
||||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
|
||||||
* tree and available online at
|
|
||||||
*
|
|
||||||
* http://www.dspace.org/license/
|
|
||||||
*/
|
|
||||||
package org.dspace.app.ldn.processor;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instuctions for removing metadata during notification processing.
|
|
||||||
*/
|
|
||||||
public class LDNMetadataRemove extends LDNMetadataChange {
|
|
||||||
|
|
||||||
private List<String> qualifiers = new ArrayList<>();
|
|
||||||
|
|
||||||
// velocity templates with notification as it contexts
|
|
||||||
private List<String> valueTemplates = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return List<String>
|
|
||||||
*/
|
|
||||||
public List<String> getQualifiers() {
|
|
||||||
return qualifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param qualifiers
|
|
||||||
*/
|
|
||||||
public void setQualifiers(List<String> qualifiers) {
|
|
||||||
this.qualifiers = qualifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return List<String>
|
|
||||||
*/
|
|
||||||
public List<String> getValueTemplates() {
|
|
||||||
return valueTemplates;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param valueTemplates
|
|
||||||
*/
|
|
||||||
public void setValueTemplates(List<String> valueTemplates) {
|
|
||||||
this.valueTemplates = valueTemplates;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -35,6 +35,15 @@ public interface LDNMessageService {
|
|||||||
*/
|
*/
|
||||||
public LDNMessageEntity find(Context context, String id) throws SQLException;
|
public LDNMessageEntity find(Context context, String id) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find all ldn messages
|
||||||
|
*
|
||||||
|
* @param context the context
|
||||||
|
* @return all ldn messages by id
|
||||||
|
* @throws SQLException If something goes wrong in the database
|
||||||
|
*/
|
||||||
|
public List<LDNMessageEntity> findAll(Context context) throws SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new LDNMessage
|
* Creates a new LDNMessage
|
||||||
*
|
*
|
||||||
@@ -118,4 +127,12 @@ public interface LDNMessageService {
|
|||||||
* @throws SQLException If something goes wrong in the database
|
* @throws SQLException If something goes wrong in the database
|
||||||
*/
|
*/
|
||||||
public NotifyRequestStatus findRequestsByItem(Context context, Item item) throws SQLException;
|
public NotifyRequestStatus findRequestsByItem(Context context, Item item) throws SQLException;
|
||||||
|
/**
|
||||||
|
* delete the provided ldn message
|
||||||
|
*
|
||||||
|
* @param context the context
|
||||||
|
* @param ldnMessage the ldn message
|
||||||
|
* @throws SQLException if something goes wrong
|
||||||
|
*/
|
||||||
|
public void delete(Context context, LDNMessageEntity ldnMessage) throws SQLException;
|
||||||
}
|
}
|
||||||
|
@@ -72,6 +72,11 @@ public class LDNMessageServiceImpl implements LDNMessageService {
|
|||||||
return ldnMessageDao.findByID(context, LDNMessageEntity.class, id);
|
return ldnMessageDao.findByID(context, LDNMessageEntity.class, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LDNMessageEntity> findAll(Context context) throws SQLException {
|
||||||
|
return ldnMessageDao.findAll(context, LDNMessageEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LDNMessageEntity create(Context context, String id) throws SQLException {
|
public LDNMessageEntity create(Context context, String id) throws SQLException {
|
||||||
return ldnMessageDao.create(context, new LDNMessageEntity(id));
|
return ldnMessageDao.create(context, new LDNMessageEntity(id));
|
||||||
@@ -304,4 +309,9 @@ public class LDNMessageServiceImpl implements LDNMessageService {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void delete(Context context, LDNMessageEntity ldnMessage) throws SQLException {
|
||||||
|
ldnMessageDao.delete(context, ldnMessage);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -377,6 +377,22 @@ public class I18nUtil {
|
|||||||
return templateName;
|
return templateName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the appropriate localized version of a ldn template according to language settings
|
||||||
|
*
|
||||||
|
* @param locale Locale for this request
|
||||||
|
* @param name String - base name of the ldn template
|
||||||
|
* @return templateName
|
||||||
|
* String - localized filename of a ldn template
|
||||||
|
*/
|
||||||
|
public static String getLDNFilename(Locale locale, String name) {
|
||||||
|
String templateFile =
|
||||||
|
DSpaceServicesFactory.getInstance().getConfigurationService().getProperty("dspace.dir") +
|
||||||
|
File.separator + "config" + File.separator + "ldn" + File.separator + name;
|
||||||
|
|
||||||
|
return getFilename(locale, templateFile, "");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates array of Locales from text list of locale-specifications.
|
* Creates array of Locales from text list of locale-specifications.
|
||||||
* Used to parse lists in DSpace configuration properties.
|
* Used to parse lists in DSpace configuration properties.
|
||||||
|
212
dspace-api/src/main/java/org/dspace/core/LDN.java
Normal file
212
dspace-api/src/main/java/org/dspace/core/LDN.java
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/**
|
||||||
|
* 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.core;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.apache.velocity.Template;
|
||||||
|
import org.apache.velocity.VelocityContext;
|
||||||
|
import org.apache.velocity.app.Velocity;
|
||||||
|
import org.apache.velocity.app.VelocityEngine;
|
||||||
|
import org.apache.velocity.exception.MethodInvocationException;
|
||||||
|
import org.apache.velocity.exception.ParseErrorException;
|
||||||
|
import org.apache.velocity.exception.ResourceNotFoundException;
|
||||||
|
import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
|
||||||
|
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing an LDN message json
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.com)
|
||||||
|
*/
|
||||||
|
public class LDN {
|
||||||
|
/**
|
||||||
|
* The content of the ldn message
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
private String contentName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments to fill out
|
||||||
|
*/
|
||||||
|
private final List<Object> arguments;
|
||||||
|
|
||||||
|
private static final Logger LOG = LogManager.getLogger();
|
||||||
|
|
||||||
|
/** Velocity template settings. */
|
||||||
|
private static final String RESOURCE_REPOSITORY_NAME = "LDN";
|
||||||
|
private static final Properties VELOCITY_PROPERTIES = new Properties();
|
||||||
|
static {
|
||||||
|
VELOCITY_PROPERTIES.put(Velocity.RESOURCE_LOADERS, "string");
|
||||||
|
VELOCITY_PROPERTIES.put("resource.loader.string.description",
|
||||||
|
"Velocity StringResource loader");
|
||||||
|
VELOCITY_PROPERTIES.put("resource.loader.string.class",
|
||||||
|
StringResourceLoader.class.getName());
|
||||||
|
VELOCITY_PROPERTIES.put("resource.loader.string.repository.name",
|
||||||
|
RESOURCE_REPOSITORY_NAME);
|
||||||
|
VELOCITY_PROPERTIES.put("resource.loader.string.repository.static",
|
||||||
|
"false");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Velocity template for the message*/
|
||||||
|
private Template template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ldn message.
|
||||||
|
*/
|
||||||
|
public LDN() {
|
||||||
|
arguments = new ArrayList<>(20);
|
||||||
|
template = null;
|
||||||
|
content = EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the content of the message. Setting this also "resets" the message
|
||||||
|
* formatting - <code>addArgument</code> will start over. Comments and any
|
||||||
|
* "Subject:" line must be stripped.
|
||||||
|
*
|
||||||
|
* @param name a name for this message
|
||||||
|
* @param cnt the content of the message
|
||||||
|
*/
|
||||||
|
public void setContent(String name, String cnt) {
|
||||||
|
content = cnt;
|
||||||
|
contentName = name;
|
||||||
|
arguments.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill out the next argument in the template
|
||||||
|
*
|
||||||
|
* @param arg the value for the next argument
|
||||||
|
*/
|
||||||
|
public void addArgument(Object arg) {
|
||||||
|
arguments.add(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the ldn message.
|
||||||
|
*
|
||||||
|
* @throws MessagingException if there was a problem sending the mail.
|
||||||
|
* @throws IOException if IO error
|
||||||
|
*/
|
||||||
|
public String generateLDNMessage() {
|
||||||
|
ConfigurationService config
|
||||||
|
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
|
||||||
|
VelocityEngine templateEngine = new VelocityEngine();
|
||||||
|
templateEngine.init(VELOCITY_PROPERTIES);
|
||||||
|
|
||||||
|
VelocityContext vctx = new VelocityContext();
|
||||||
|
vctx.put("config", new LDN.UnmodifiableConfigurationService(config));
|
||||||
|
vctx.put("params", Collections.unmodifiableList(arguments));
|
||||||
|
|
||||||
|
if (null == template) {
|
||||||
|
if (StringUtils.isBlank(content)) {
|
||||||
|
LOG.error("template has no content");
|
||||||
|
throw new RuntimeException("template has no content");
|
||||||
|
}
|
||||||
|
// No template, so use a String of content.
|
||||||
|
StringResourceRepository repo = (StringResourceRepository)
|
||||||
|
templateEngine.getApplicationAttribute(RESOURCE_REPOSITORY_NAME);
|
||||||
|
repo.putStringResource(contentName, content);
|
||||||
|
// Turn content into a template.
|
||||||
|
template = templateEngine.getTemplate(contentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
try {
|
||||||
|
template.merge(vctx, writer);
|
||||||
|
} catch (MethodInvocationException | ParseErrorException
|
||||||
|
| ResourceNotFoundException ex) {
|
||||||
|
LOG.error("Template not merged: {}", ex.getMessage());
|
||||||
|
throw new RuntimeException("Template not merged", ex);
|
||||||
|
}
|
||||||
|
return writer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the VTL template for a ldn message. The message is suitable
|
||||||
|
* for inserting values using Apache Velocity.
|
||||||
|
*
|
||||||
|
* @param ldnMessageFile
|
||||||
|
* full name for the ldn template, for example "/dspace/config/ldn/request-review".
|
||||||
|
*
|
||||||
|
* @return the ldn object, configured with body.
|
||||||
|
*
|
||||||
|
* @throws IOException if IO error,
|
||||||
|
* if the template couldn't be found, or there was some other
|
||||||
|
* error reading the template
|
||||||
|
*/
|
||||||
|
public static LDN getLDNMessage(String ldnMessageFile)
|
||||||
|
throws IOException {
|
||||||
|
StringBuilder contentBuffer = new StringBuilder();
|
||||||
|
try (
|
||||||
|
InputStream is = new FileInputStream(ldnMessageFile);
|
||||||
|
InputStreamReader ir = new InputStreamReader(is, "UTF-8");
|
||||||
|
BufferedReader reader = new BufferedReader(ir);
|
||||||
|
) {
|
||||||
|
boolean more = true;
|
||||||
|
while (more) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
more = false;
|
||||||
|
} else {
|
||||||
|
contentBuffer.append(line);
|
||||||
|
contentBuffer.append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LDN ldn = new LDN();
|
||||||
|
ldn.setContent(ldnMessageFile, contentBuffer.toString());
|
||||||
|
return ldn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap ConfigurationService to prevent templates from modifying
|
||||||
|
* the configuration.
|
||||||
|
*/
|
||||||
|
public static class UnmodifiableConfigurationService {
|
||||||
|
private final ConfigurationService configurationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swallow an instance of ConfigurationService.
|
||||||
|
*
|
||||||
|
* @param cs the real instance, to be wrapped.
|
||||||
|
*/
|
||||||
|
public UnmodifiableConfigurationService(ConfigurationService cs) {
|
||||||
|
configurationService = cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a key in the actual ConfigurationService.
|
||||||
|
*
|
||||||
|
* @param key to be looked up in the DSpace configuration.
|
||||||
|
* @return whatever value ConfigurationService associates with {@code key}.
|
||||||
|
*/
|
||||||
|
public String get(String key) {
|
||||||
|
return configurationService.getProperty(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -95,14 +95,14 @@ loglevel.dspace = INFO
|
|||||||
# IIIF TEST SETTINGS #
|
# IIIF TEST SETTINGS #
|
||||||
########################
|
########################
|
||||||
iiif.enabled = true
|
iiif.enabled = true
|
||||||
event.dispatcher.default.consumers = versioning, discovery, eperson, orcidqueue, iiif, qaeventsdelete
|
event.dispatcher.default.consumers = versioning, discovery, eperson, orcidqueue, iiif, qaeventsdelete, ldnmessage
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# CUSTOM UNIT / INTEGRATION TEST SETTINGS #
|
# CUSTOM UNIT / INTEGRATION TEST SETTINGS #
|
||||||
###########################################
|
###########################################
|
||||||
# custom dispatcher to be used by dspace-api IT that doesn't need SOLR
|
# custom dispatcher to be used by dspace-api IT that doesn't need SOLR
|
||||||
event.dispatcher.exclude-discovery.class = org.dspace.event.BasicDispatcher
|
event.dispatcher.exclude-discovery.class = org.dspace.event.BasicDispatcher
|
||||||
event.dispatcher.exclude-discovery.consumers = versioning, eperson, qaeventsdelete
|
event.dispatcher.exclude-discovery.consumers = versioning, eperson, qaeventsdelete, ldnmessage
|
||||||
|
|
||||||
# Configure authority control for Unit Testing (in DSpaceControlledVocabularyTest)
|
# Configure authority control for Unit Testing (in DSpaceControlledVocabularyTest)
|
||||||
# (This overrides default, commented out settings in dspace.cfg)
|
# (This overrides default, commented out settings in dspace.cfg)
|
||||||
|
@@ -0,0 +1,378 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import static org.dspace.app.ldn.LDNMessageEntity.QUEUE_STATUS_QUEUED;
|
||||||
|
import static org.dspace.matcher.NotifyServiceEntityMatcher.matchesNotifyServiceEntity;
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.app.ldn.factory.NotifyServiceFactory;
|
||||||
|
import org.dspace.app.ldn.model.Notification;
|
||||||
|
import org.dspace.app.ldn.service.LDNMessageService;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.EPersonBuilder;
|
||||||
|
import org.dspace.builder.NotifyServiceBuilder;
|
||||||
|
import org.dspace.builder.WorkspaceItemBuilder;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.WorkspaceItem;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.workflow.WorkflowItem;
|
||||||
|
import org.dspace.workflow.WorkflowService;
|
||||||
|
import org.dspace.workflow.factory.WorkflowServiceFactory;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration Tests against {@link LDNMessageConsumer}
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.com)
|
||||||
|
*/
|
||||||
|
public class LDNMessageConsumerIT extends AbstractIntegrationTestWithDatabase {
|
||||||
|
|
||||||
|
private Collection collection;
|
||||||
|
private EPerson submitter;
|
||||||
|
|
||||||
|
private LDNMessageService ldnMessageService = NotifyServiceFactory.getInstance().getLDNMessageService();
|
||||||
|
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
private WorkflowService workflowService = WorkflowServiceFactory.getInstance().getWorkflowService();
|
||||||
|
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
//** GIVEN **
|
||||||
|
//1. create a normal user to use as submitter
|
||||||
|
submitter = EPersonBuilder.createEPerson(context)
|
||||||
|
.withEmail("submitter@example.com")
|
||||||
|
.withPassword(password)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//2. A community with one collection.
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
collection = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.withSubmitterGroup(submitter)
|
||||||
|
.build();
|
||||||
|
context.setCurrentUser(submitter);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLDNMessageConsumerRequestReview() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
NotifyServiceEntity notifyService =
|
||||||
|
NotifyServiceBuilder.createNotifyServiceBuilder(context)
|
||||||
|
.withName("service name")
|
||||||
|
.withDescription("service description")
|
||||||
|
.withUrl("https://service.ldn.org/about")
|
||||||
|
.withLdnUrl("https://service.ldn.org/inbox")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//3. a workspace item ready to go
|
||||||
|
WorkspaceItem workspaceItem =
|
||||||
|
WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Submission Item")
|
||||||
|
.withIssueDate("2023-11-20")
|
||||||
|
.withCOARNotifyService(notifyService, "request-review")
|
||||||
|
.withFulltext("test.txt", "test", InputStream.nullInputStream())
|
||||||
|
.grantLicense()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkflowItem workflowItem = workflowService.start(context, workspaceItem);
|
||||||
|
Item item = workflowItem.getItem();
|
||||||
|
context.dispatchEvents();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.findAll(context).stream().findFirst().orElse(null);
|
||||||
|
|
||||||
|
|
||||||
|
assertThat(notifyService, matchesNotifyServiceEntity(ldnMessage.getTarget()));
|
||||||
|
assertEquals(workflowItem.getItem().getID(), ldnMessage.getObject().getID());
|
||||||
|
assertEquals(QUEUE_STATUS_QUEUED, ldnMessage.getQueueStatus());
|
||||||
|
assertNull(ldnMessage.getOrigin());
|
||||||
|
assertNotNull(ldnMessage.getMessage());
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
Notification notification = mapper.readValue(ldnMessage.getMessage(), Notification.class);
|
||||||
|
|
||||||
|
// check id
|
||||||
|
assertThat(notification.getId(), containsString("urn:uuid:"));
|
||||||
|
|
||||||
|
// check object
|
||||||
|
assertEquals(notification.getObject().getId(),
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle());
|
||||||
|
assertEquals(notification.getObject().getIetfCiteAs(),
|
||||||
|
itemService.getMetadataByMetadataString(item, "dc.identifier.uri").get(0).getValue());
|
||||||
|
assertEquals(notification.getObject().getUrl().getId(),
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/bitstreams/" +
|
||||||
|
item.getBundles(Constants.CONTENT_BUNDLE_NAME).get(0).getBitstreams().get(0).getID() + "/download");
|
||||||
|
|
||||||
|
// check target
|
||||||
|
assertEquals(notification.getTarget().getId(), notifyService.getUrl());
|
||||||
|
assertEquals(notification.getTarget().getInbox(), notifyService.getLdnUrl());
|
||||||
|
assertEquals(notification.getTarget().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check origin
|
||||||
|
assertEquals(notification.getOrigin().getId(), configurationService.getProperty("dspace.ui.url"));
|
||||||
|
assertEquals(notification.getOrigin().getInbox(), configurationService.getProperty("ldn.notify.inbox"));
|
||||||
|
assertEquals(notification.getOrigin().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check actor
|
||||||
|
assertEquals(notification.getActor().getId(), configurationService.getProperty("dspace.ui.url"));
|
||||||
|
assertEquals(notification.getActor().getName(), configurationService.getProperty("dspace.name"));
|
||||||
|
assertEquals(notification.getOrigin().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check types
|
||||||
|
assertEquals(notification.getType(), Set.of("coar-notify:ReviewAction", "Offer"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLDNMessageConsumerRequestEndorsement() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
NotifyServiceEntity notifyService =
|
||||||
|
NotifyServiceBuilder.createNotifyServiceBuilder(context)
|
||||||
|
.withName("service name")
|
||||||
|
.withDescription("service description")
|
||||||
|
.withUrl("https://service.ldn.org/about")
|
||||||
|
.withLdnUrl("https://service.ldn.org/inbox")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//3. a workspace item ready to go
|
||||||
|
WorkspaceItem workspaceItem =
|
||||||
|
WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Submission Item")
|
||||||
|
.withIssueDate("2023-11-20")
|
||||||
|
.withCOARNotifyService(notifyService, "request-endorsement")
|
||||||
|
.withFulltext("test.txt", "test", InputStream.nullInputStream())
|
||||||
|
.grantLicense()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkflowItem workflowItem = workflowService.start(context, workspaceItem);
|
||||||
|
Item item = workflowItem.getItem();
|
||||||
|
context.dispatchEvents();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.findAll(context).stream().findFirst().orElse(null);
|
||||||
|
|
||||||
|
|
||||||
|
assertThat(notifyService, matchesNotifyServiceEntity(ldnMessage.getTarget()));
|
||||||
|
assertEquals(workflowItem.getItem().getID(), ldnMessage.getObject().getID());
|
||||||
|
assertEquals(QUEUE_STATUS_QUEUED, ldnMessage.getQueueStatus());
|
||||||
|
assertNull(ldnMessage.getOrigin());
|
||||||
|
assertNotNull(ldnMessage.getMessage());
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
Notification notification = mapper.readValue(ldnMessage.getMessage(), Notification.class);
|
||||||
|
|
||||||
|
// check id
|
||||||
|
assertThat(notification.getId(), containsString("urn:uuid:"));
|
||||||
|
|
||||||
|
// check object
|
||||||
|
assertEquals(notification.getObject().getId(),
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle());
|
||||||
|
assertEquals(notification.getObject().getIetfCiteAs(),
|
||||||
|
itemService.getMetadataByMetadataString(item, "dc.identifier.uri").get(0).getValue());
|
||||||
|
assertEquals(notification.getObject().getUrl().getId(),
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/bitstreams/" +
|
||||||
|
item.getBundles(Constants.CONTENT_BUNDLE_NAME).get(0).getBitstreams().get(0).getID() + "/download");
|
||||||
|
|
||||||
|
// check target
|
||||||
|
assertEquals(notification.getTarget().getId(), notifyService.getUrl());
|
||||||
|
assertEquals(notification.getTarget().getInbox(), notifyService.getLdnUrl());
|
||||||
|
assertEquals(notification.getTarget().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check origin
|
||||||
|
assertEquals(notification.getOrigin().getId(), configurationService.getProperty("dspace.ui.url"));
|
||||||
|
assertEquals(notification.getOrigin().getInbox(), configurationService.getProperty("ldn.notify.inbox"));
|
||||||
|
assertEquals(notification.getOrigin().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check actor
|
||||||
|
assertEquals(notification.getActor().getId(), configurationService.getProperty("dspace.ui.url"));
|
||||||
|
assertEquals(notification.getActor().getName(), configurationService.getProperty("dspace.name"));
|
||||||
|
assertEquals(notification.getOrigin().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check types
|
||||||
|
assertEquals(notification.getType(), Set.of("coar-notify:EndorsementAction", "Offer"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLDNMessageConsumerRequestIngest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
NotifyServiceEntity notifyService =
|
||||||
|
NotifyServiceBuilder.createNotifyServiceBuilder(context)
|
||||||
|
.withName("service name")
|
||||||
|
.withDescription("service description")
|
||||||
|
.withUrl("https://service.ldn.org/about")
|
||||||
|
.withLdnUrl("https://service.ldn.org/inbox")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//3. a workspace item ready to go
|
||||||
|
WorkspaceItem workspaceItem =
|
||||||
|
WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Submission Item")
|
||||||
|
.withIssueDate("2023-11-20")
|
||||||
|
.withCOARNotifyService(notifyService, "request-ingest")
|
||||||
|
.withFulltext("test.txt", "test", InputStream.nullInputStream())
|
||||||
|
.grantLicense()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkflowItem workflowItem = workflowService.start(context, workspaceItem);
|
||||||
|
Item item = workflowItem.getItem();
|
||||||
|
context.dispatchEvents();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.findAll(context).stream().findFirst().orElse(null);
|
||||||
|
|
||||||
|
|
||||||
|
assertThat(notifyService, matchesNotifyServiceEntity(ldnMessage.getTarget()));
|
||||||
|
assertEquals(workflowItem.getItem().getID(), ldnMessage.getObject().getID());
|
||||||
|
assertEquals(QUEUE_STATUS_QUEUED, ldnMessage.getQueueStatus());
|
||||||
|
assertNull(ldnMessage.getOrigin());
|
||||||
|
assertNotNull(ldnMessage.getMessage());
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
Notification notification = mapper.readValue(ldnMessage.getMessage(), Notification.class);
|
||||||
|
|
||||||
|
// check id
|
||||||
|
assertThat(notification.getId(), containsString("urn:uuid:"));
|
||||||
|
|
||||||
|
// check object
|
||||||
|
assertEquals(notification.getObject().getId(),
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/handle/" + item.getHandle());
|
||||||
|
assertEquals(notification.getObject().getIetfCiteAs(),
|
||||||
|
itemService.getMetadataByMetadataString(item, "dc.identifier.uri").get(0).getValue());
|
||||||
|
assertEquals(notification.getObject().getUrl().getId(),
|
||||||
|
configurationService.getProperty("dspace.ui.url") + "/bitstreams/" +
|
||||||
|
item.getBundles(Constants.CONTENT_BUNDLE_NAME).get(0).getBitstreams().get(0).getID() + "/download");
|
||||||
|
|
||||||
|
// check target
|
||||||
|
assertEquals(notification.getTarget().getId(), notifyService.getUrl());
|
||||||
|
assertEquals(notification.getTarget().getInbox(), notifyService.getLdnUrl());
|
||||||
|
assertEquals(notification.getTarget().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check origin
|
||||||
|
assertEquals(notification.getOrigin().getId(), configurationService.getProperty("dspace.ui.url"));
|
||||||
|
assertEquals(notification.getOrigin().getInbox(), configurationService.getProperty("ldn.notify.inbox"));
|
||||||
|
assertEquals(notification.getOrigin().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check actor
|
||||||
|
assertEquals(notification.getActor().getId(), configurationService.getProperty("dspace.ui.url"));
|
||||||
|
assertEquals(notification.getActor().getName(), configurationService.getProperty("dspace.name"));
|
||||||
|
assertEquals(notification.getOrigin().getType(), Set.of("Service"));
|
||||||
|
|
||||||
|
// check types
|
||||||
|
assertEquals(notification.getType(), Set.of("coar-notify:IngestAction", "Offer"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLDNMessageConsumerRequestFake() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
NotifyServiceEntity notifyService =
|
||||||
|
NotifyServiceBuilder.createNotifyServiceBuilder(context)
|
||||||
|
.withName("service name")
|
||||||
|
.withDescription("service description")
|
||||||
|
.withUrl("https://service.ldn.org/about")
|
||||||
|
.withLdnUrl("https://service.ldn.org/inbox")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//3. a workspace item ready to go
|
||||||
|
WorkspaceItem workspaceItem =
|
||||||
|
WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Submission Item")
|
||||||
|
.withIssueDate("2023-11-20")
|
||||||
|
.withCOARNotifyService(notifyService, "request-fake")
|
||||||
|
.withFulltext("test.txt", "test", InputStream.nullInputStream())
|
||||||
|
.grantLicense()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
workflowService.start(context, workspaceItem);
|
||||||
|
context.dispatchEvents();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.findAll(context).stream().findFirst().orElse(null);
|
||||||
|
|
||||||
|
assertNull(ldnMessage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLDNMessageConsumerNoRequests() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
//3. a workspace item ready to go
|
||||||
|
WorkspaceItem workspaceItem =
|
||||||
|
WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Submission Item")
|
||||||
|
.withIssueDate("2023-11-20")
|
||||||
|
.grantLicense()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
workflowService.start(context, workspaceItem);
|
||||||
|
context.dispatchEvents();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.findAll(context).stream().findFirst().orElse(null);
|
||||||
|
|
||||||
|
assertNull(ldnMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@After
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
List<LDNMessageEntity> ldnMessageEntities = ldnMessageService.findAll(context);
|
||||||
|
if (CollectionUtils.isNotEmpty(ldnMessageEntities)) {
|
||||||
|
ldnMessageEntities.forEach(ldnMessage -> {
|
||||||
|
try {
|
||||||
|
ldnMessageService.delete(context, ldnMessage);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,218 @@
|
|||||||
|
/**
|
||||||
|
* 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.action;
|
||||||
|
|
||||||
|
import static org.dspace.app.ldn.action.ActionStatus.ABORT;
|
||||||
|
import static org.dspace.app.ldn.action.ActionStatus.CONTINUE;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.app.ldn.LDNMessageEntity;
|
||||||
|
import org.dspace.app.ldn.NotifyServiceEntity;
|
||||||
|
import org.dspace.app.ldn.factory.NotifyServiceFactory;
|
||||||
|
import org.dspace.app.ldn.model.Notification;
|
||||||
|
import org.dspace.app.ldn.service.LDNMessageService;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.EPersonBuilder;
|
||||||
|
import org.dspace.builder.NotifyServiceBuilder;
|
||||||
|
import org.dspace.builder.WorkspaceItemBuilder;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.WorkspaceItem;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.workflow.WorkflowItem;
|
||||||
|
import org.dspace.workflow.WorkflowService;
|
||||||
|
import org.dspace.workflow.factory.WorkflowServiceFactory;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration Tests against {@link SendLDNMessageAction}
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.com)
|
||||||
|
*/
|
||||||
|
public class SendLDNMessageActionIT extends AbstractIntegrationTestWithDatabase {
|
||||||
|
|
||||||
|
private Collection collection;
|
||||||
|
private EPerson submitter;
|
||||||
|
|
||||||
|
private LDNMessageService ldnMessageService = NotifyServiceFactory.getInstance().getLDNMessageService();
|
||||||
|
private WorkflowService workflowService = WorkflowServiceFactory.getInstance().getWorkflowService();
|
||||||
|
private SendLDNMessageAction sendLDNMessageAction;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
sendLDNMessageAction = new SendLDNMessageAction();
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
//** GIVEN **
|
||||||
|
//1. create a normal user to use as submitter
|
||||||
|
submitter = EPersonBuilder.createEPerson(context)
|
||||||
|
.withEmail("submitter@example.com")
|
||||||
|
.withPassword(password)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//2. A community with one collection.
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
collection = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withName("Collection 1")
|
||||||
|
.withSubmitterGroup(submitter)
|
||||||
|
.build();
|
||||||
|
context.setCurrentUser(submitter);
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLDNMessageConsumerRequestReview() throws Exception {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
NotifyServiceEntity notifyService =
|
||||||
|
NotifyServiceBuilder.createNotifyServiceBuilder(context)
|
||||||
|
.withName("service name")
|
||||||
|
.withDescription("service description")
|
||||||
|
.withUrl("https://www.notify-inbox.info/")
|
||||||
|
.withLdnUrl("https://notify-inbox.info/inbox/")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//3. a workspace item ready to go
|
||||||
|
WorkspaceItem workspaceItem =
|
||||||
|
WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Submission Item")
|
||||||
|
.withIssueDate("2023-11-20")
|
||||||
|
.withCOARNotifyService(notifyService, "request-review")
|
||||||
|
.withFulltext("test.txt", "test", InputStream.nullInputStream())
|
||||||
|
.grantLicense()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkflowItem workflowItem = workflowService.start(context, workspaceItem);
|
||||||
|
Item item = workflowItem.getItem();
|
||||||
|
context.dispatchEvents();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.findAll(context).stream().findFirst().orElse(null);
|
||||||
|
|
||||||
|
ldnMessage.getQueueStatus();
|
||||||
|
|
||||||
|
Notification notification = mapper.readValue(ldnMessage.getMessage(), Notification.class);
|
||||||
|
|
||||||
|
assertEquals(sendLDNMessageAction.execute(context, notification, item), CONTINUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLDNMessageConsumerRequestReviewGotRedirection() throws Exception {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
// ldnUrl should be https://notify-inbox.info/inbox/
|
||||||
|
// but used https://notify-inbox.info/inbox for redirection
|
||||||
|
NotifyServiceEntity notifyService =
|
||||||
|
NotifyServiceBuilder.createNotifyServiceBuilder(context)
|
||||||
|
.withName("service name")
|
||||||
|
.withDescription("service description")
|
||||||
|
.withUrl("https://www.notify-inbox.info/")
|
||||||
|
.withLdnUrl("https://notify-inbox.info/inbox")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//3. a workspace item ready to go
|
||||||
|
WorkspaceItem workspaceItem =
|
||||||
|
WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Submission Item")
|
||||||
|
.withIssueDate("2023-11-20")
|
||||||
|
.withCOARNotifyService(notifyService, "request-review")
|
||||||
|
.withFulltext("test.txt", "test", InputStream.nullInputStream())
|
||||||
|
.grantLicense()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkflowItem workflowItem = workflowService.start(context, workspaceItem);
|
||||||
|
Item item = workflowItem.getItem();
|
||||||
|
context.dispatchEvents();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.findAll(context).stream().findFirst().orElse(null);
|
||||||
|
|
||||||
|
ldnMessage.getQueueStatus();
|
||||||
|
|
||||||
|
Notification notification = mapper.readValue(ldnMessage.getMessage(), Notification.class);
|
||||||
|
|
||||||
|
assertEquals(sendLDNMessageAction.execute(context, notification, item), CONTINUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLDNMessageConsumerRequestReviewWithInvalidLdnUrl() throws Exception {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
NotifyServiceEntity notifyService =
|
||||||
|
NotifyServiceBuilder.createNotifyServiceBuilder(context)
|
||||||
|
.withName("service name")
|
||||||
|
.withDescription("service description")
|
||||||
|
.withUrl("https://www.notify-inbox.info/")
|
||||||
|
.withLdnUrl("https://notify-inbox.info/invalidLdnUrl/")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//3. a workspace item ready to go
|
||||||
|
WorkspaceItem workspaceItem =
|
||||||
|
WorkspaceItemBuilder.createWorkspaceItem(context, collection)
|
||||||
|
.withTitle("Submission Item")
|
||||||
|
.withIssueDate("2023-11-20")
|
||||||
|
.withCOARNotifyService(notifyService, "request-review")
|
||||||
|
.withFulltext("test.txt", "test", InputStream.nullInputStream())
|
||||||
|
.grantLicense()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkflowItem workflowItem = workflowService.start(context, workspaceItem);
|
||||||
|
Item item = workflowItem.getItem();
|
||||||
|
context.dispatchEvents();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
LDNMessageEntity ldnMessage =
|
||||||
|
ldnMessageService.findAll(context).stream().findFirst().orElse(null);
|
||||||
|
|
||||||
|
ldnMessage.getQueueStatus();
|
||||||
|
|
||||||
|
Notification notification = mapper.readValue(ldnMessage.getMessage(), Notification.class);
|
||||||
|
|
||||||
|
assertEquals(sendLDNMessageAction.execute(context, notification, item), ABORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@After
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
List<LDNMessageEntity> ldnMessageEntities = ldnMessageService.findAll(context);
|
||||||
|
if (CollectionUtils.isNotEmpty(ldnMessageEntities)) {
|
||||||
|
ldnMessageEntities.forEach(ldnMessage -> {
|
||||||
|
try {
|
||||||
|
ldnMessageService.delete(context, ldnMessage);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 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.matcher;
|
||||||
|
|
||||||
|
import org.dspace.app.ldn.NotifyServiceEntity;
|
||||||
|
import org.hamcrest.Description;
|
||||||
|
import org.hamcrest.Matcher;
|
||||||
|
import org.hamcrest.TypeSafeMatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link Matcher} to match a NotifyServiceEntity by all its
|
||||||
|
* attributes.
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.com)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class NotifyServiceEntityMatcher extends TypeSafeMatcher<NotifyServiceEntity> {
|
||||||
|
|
||||||
|
private final NotifyServiceEntity expectedEntity;
|
||||||
|
|
||||||
|
private NotifyServiceEntityMatcher(NotifyServiceEntity expectedEntity) {
|
||||||
|
this.expectedEntity = expectedEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NotifyServiceEntityMatcher matchesNotifyServiceEntity(NotifyServiceEntity expectedEntity) {
|
||||||
|
return new NotifyServiceEntityMatcher(expectedEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean matchesSafely(NotifyServiceEntity actualEntity) {
|
||||||
|
return actualEntity.getName().equals(expectedEntity.getName()) &&
|
||||||
|
actualEntity.getDescription().equals(expectedEntity.getDescription()) &&
|
||||||
|
actualEntity.getUrl().equals(expectedEntity.getUrl()) &&
|
||||||
|
actualEntity.getLdnUrl().equals(expectedEntity.getLdnUrl()) &&
|
||||||
|
actualEntity.getInboundPatterns() == expectedEntity.getInboundPatterns() &&
|
||||||
|
actualEntity.getOutboundPatterns() == expectedEntity.getOutboundPatterns() &&
|
||||||
|
actualEntity.isEnabled() == expectedEntity.isEnabled() &&
|
||||||
|
actualEntity.getScore() == expectedEntity.getScore();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void describeTo(Description description) {
|
||||||
|
description.appendText("a Notify Service Entity with the following attributes:")
|
||||||
|
.appendText(", name ").appendValue(expectedEntity.getName())
|
||||||
|
.appendText(", description ").appendValue(expectedEntity.getDescription())
|
||||||
|
.appendText(", URL ").appendValue(expectedEntity.getUrl())
|
||||||
|
.appendText(", LDN URL ").appendValue(expectedEntity.getLdnUrl())
|
||||||
|
.appendText(", inbound patterns ").appendValue(expectedEntity.getInboundPatterns())
|
||||||
|
.appendText(", outbound patterns ").appendValue(expectedEntity.getOutboundPatterns())
|
||||||
|
.appendText(", enabled ").appendValue(expectedEntity.isEnabled())
|
||||||
|
.appendText(", score ").appendValue(expectedEntity.getScore());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -780,7 +780,7 @@ event.dispatcher.default.class = org.dspace.event.BasicDispatcher
|
|||||||
# Add rdf here, if you are using dspace-rdf to export your repository content as RDF.
|
# Add rdf here, if you are using dspace-rdf to export your repository content as RDF.
|
||||||
# Add iiif here, if you are using dspace-iiif.
|
# Add iiif here, if you are using dspace-iiif.
|
||||||
# Add orcidqueue here, if the integration with ORCID is configured and wish to enable the synchronization queue functionality
|
# Add orcidqueue here, if the integration with ORCID is configured and wish to enable the synchronization queue functionality
|
||||||
event.dispatcher.default.consumers = versioning, discovery, eperson, qaeventsdelete
|
event.dispatcher.default.consumers = versioning, discovery, eperson, qaeventsdelete, ldnmessage
|
||||||
|
|
||||||
# The noindex dispatcher will not create search or browse indexes (useful for batch item imports)
|
# The noindex dispatcher will not create search or browse indexes (useful for batch item imports)
|
||||||
event.dispatcher.noindex.class = org.dspace.event.BasicDispatcher
|
event.dispatcher.noindex.class = org.dspace.event.BasicDispatcher
|
||||||
@@ -826,6 +826,10 @@ event.consumer.iiif.filters = Item+Modify:Item+Modify_Metadata:Item+Delete:Item+
|
|||||||
event.consumer.orcidqueue.class = org.dspace.orcid.consumer.OrcidQueueConsumer
|
event.consumer.orcidqueue.class = org.dspace.orcid.consumer.OrcidQueueConsumer
|
||||||
event.consumer.orcidqueue.filters = Item+Install|Modify|Modify_Metadata|Delete|Remove
|
event.consumer.orcidqueue.filters = Item+Install|Modify|Modify_Metadata|Delete|Remove
|
||||||
|
|
||||||
|
# consumer to store LDN Messages
|
||||||
|
event.consumer.ldnmessage.class = org.dspace.app.ldn.LDNMessageConsumer
|
||||||
|
event.consumer.ldnmessage.filters = Item+Install
|
||||||
|
|
||||||
# ...set to true to enable testConsumer messages to standard output
|
# ...set to true to enable testConsumer messages to standard output
|
||||||
#testConsumer.verbose = true
|
#testConsumer.verbose = true
|
||||||
|
|
||||||
|
52
dspace/config/ldn/request-endorsement
Normal file
52
dspace/config/ldn/request-endorsement
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
## generate LDN message json when request-endorsement of an item
|
||||||
|
##
|
||||||
|
## Parameters: {0} config 'dspace.ui.url'
|
||||||
|
## {1} config 'ldn.notify.inbox'
|
||||||
|
## {2} config 'dspace.name'
|
||||||
|
## {3} Notify Service url
|
||||||
|
## {4} Notify Service ldnUrl
|
||||||
|
## {5} 'dspace.ui.url'/handle/xxxx/yyy
|
||||||
|
## {6} metadata value of 'dc.identifier.uri'
|
||||||
|
## {7} the url to the primary bitstream or the first bitstream in the ORIGINAL bundle if there is no primary bitstream. The url is 'dspace.ui.url'/bitstreams/:uuid/download
|
||||||
|
## {8} the bitstream MimeType or get User Format MimeType if getFormat is 'Unknown'
|
||||||
|
## {9} id of the created LDNMessage
|
||||||
|
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://purl.org/coar/notify"
|
||||||
|
],
|
||||||
|
"actor": {
|
||||||
|
"id": "${params[0]}",
|
||||||
|
"name": "${params[2]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"id": "${params[9]}",
|
||||||
|
"object": {
|
||||||
|
"id": "${params[5]}",
|
||||||
|
"ietf:cite-as": "${params[6]}",
|
||||||
|
"type": "sorg:AboutPage",
|
||||||
|
"url": {
|
||||||
|
"id": "${params[7]}",
|
||||||
|
"mediaType": "${params[8]}",
|
||||||
|
"type": [
|
||||||
|
"Article",
|
||||||
|
"sorg:ScholarlyArticle"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"id": "${params[0]}",
|
||||||
|
"inbox": "${params[1]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"id": "${params[3]}",
|
||||||
|
"inbox": "${params[4]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"Offer",
|
||||||
|
"coar-notify:EndorsementAction"
|
||||||
|
]
|
||||||
|
}
|
52
dspace/config/ldn/request-ingest
Normal file
52
dspace/config/ldn/request-ingest
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
## generate LDN message json when request-ingest of an item
|
||||||
|
##
|
||||||
|
## Parameters: {0} config 'dspace.ui.url'
|
||||||
|
## {1} config 'ldn.notify.inbox'
|
||||||
|
## {2} config 'dspace.name'
|
||||||
|
## {3} Notify Service url
|
||||||
|
## {4} Notify Service ldnUrl
|
||||||
|
## {5} 'dspace.ui.url'/handle/xxxx/yyy
|
||||||
|
## {6} metadata value of 'dc.identifier.uri'
|
||||||
|
## {7} the url to the primary bitstream or the first bitstream in the ORIGINAL bundle if there is no primary bitstream. The url is 'dspace.ui.url'/bitstreams/:uuid/download
|
||||||
|
## {8} the bitstream MimeType or get User Format MimeType if getFormat is 'Unknown'
|
||||||
|
## {9} id of the created LDNMessage
|
||||||
|
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://purl.org/coar/notify"
|
||||||
|
],
|
||||||
|
"actor": {
|
||||||
|
"id": "${params[0]}",
|
||||||
|
"name": "${params[2]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"id": "${params[9]}",
|
||||||
|
"object": {
|
||||||
|
"id": "${params[5]}",
|
||||||
|
"ietf:cite-as": "${params[6]}",
|
||||||
|
"type": "sorg:AboutPage",
|
||||||
|
"url": {
|
||||||
|
"id": "${params[7]}",
|
||||||
|
"mediaType": "${params[8]}",
|
||||||
|
"type": [
|
||||||
|
"Article",
|
||||||
|
"sorg:ScholarlyArticle"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"id": "${params[0]}",
|
||||||
|
"inbox": "${params[1]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"id": "${params[3]}",
|
||||||
|
"inbox": "${params[4]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"Offer",
|
||||||
|
"coar-notify:IngestAction"
|
||||||
|
]
|
||||||
|
}
|
52
dspace/config/ldn/request-review
Normal file
52
dspace/config/ldn/request-review
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
## generate LDN message json when request-review of an item
|
||||||
|
##
|
||||||
|
## Parameters: {0} config 'dspace.ui.url'
|
||||||
|
## {1} config 'ldn.notify.inbox'
|
||||||
|
## {2} config 'dspace.name'
|
||||||
|
## {3} Notify Service url
|
||||||
|
## {4} Notify Service ldnUrl
|
||||||
|
## {5} 'dspace.ui.url'/handle/xxxx/yyy
|
||||||
|
## {6} metadata value of 'dc.identifier.uri'
|
||||||
|
## {7} the url to the primary bitstream or the first bitstream in the ORIGINAL bundle if there is no primary bitstream. The url is 'dspace.ui.url'/bitstreams/:uuid/download
|
||||||
|
## {8} the bitstream MimeType or get User Format MimeType if getFormat is 'Unknown'
|
||||||
|
## {9} id of the created LDNMessage
|
||||||
|
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://purl.org/coar/notify"
|
||||||
|
],
|
||||||
|
"actor": {
|
||||||
|
"id": "${params[0]}",
|
||||||
|
"name": "${params[2]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"id": "${params[9]}",
|
||||||
|
"object": {
|
||||||
|
"id": "${params[5]}",
|
||||||
|
"ietf:cite-as": "${params[6]}",
|
||||||
|
"type": "sorg:AboutPage",
|
||||||
|
"url": {
|
||||||
|
"id": "${params[7]}",
|
||||||
|
"mediaType": "${params[8]}",
|
||||||
|
"type": [
|
||||||
|
"Article",
|
||||||
|
"sorg:ScholarlyArticle"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"id": "${params[0]}",
|
||||||
|
"inbox": "${params[1]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"id": "${params[3]}",
|
||||||
|
"inbox": "${params[4]}",
|
||||||
|
"type": "Service"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"Offer",
|
||||||
|
"coar-notify:ReviewAction"
|
||||||
|
]
|
||||||
|
}
|
@@ -26,3 +26,8 @@ ldn.processor.max.attempts = 5
|
|||||||
# of the message. LDN Message with a future queue_timeout is not elaborated. This property is used to calculateas:
|
# of the message. LDN Message with a future queue_timeout is not elaborated. This property is used to calculateas:
|
||||||
# a new timeout, such as: new_timeout = now + ldn.processor.queue.msg.timeout (in minutes)
|
# a new timeout, such as: new_timeout = now + ldn.processor.queue.msg.timeout (in minutes)
|
||||||
ldn.processor.queue.msg.timeout = 60
|
ldn.processor.queue.msg.timeout = 60
|
||||||
|
|
||||||
|
|
||||||
|
# EMAIL CONFIGURATION
|
||||||
|
|
||||||
|
ldn.notification.email = ${mail.admin}
|
||||||
|
@@ -57,9 +57,6 @@
|
|||||||
|
|
||||||
<bean id="supervisionOrderServiceFactory" class="org.dspace.supervision.factory.SupervisionOrderServiceFactoryImpl"/>
|
<bean id="supervisionOrderServiceFactory" class="org.dspace.supervision.factory.SupervisionOrderServiceFactoryImpl"/>
|
||||||
|
|
||||||
<!-- LDN COAR Notify services -->
|
|
||||||
<bean id="ldnBusinessDelegateFactory" class="org.dspace.app.ldn.factory.LDNBusinessDelegateFactoryImpl"/>
|
|
||||||
|
|
||||||
<bean id="notifyServiceFactory" class="org.dspace.app.ldn.factory.NotifyServiceFactoryImpl"/>
|
<bean id="notifyServiceFactory" class="org.dspace.app.ldn.factory.NotifyServiceFactoryImpl"/>
|
||||||
|
|
||||||
<bean id="ldnMessageServiceFactory" class="org.dspace.app.ldn.factory.LDNMessageServiceFactoryImpl"/>
|
<bean id="ldnMessageServiceFactory" class="org.dspace.app.ldn.factory.LDNMessageServiceFactoryImpl"/>
|
||||||
|
@@ -22,10 +22,9 @@
|
|||||||
<bean class="org.dspace.app.ldn.service.impl.NotifyServiceOutboundPatternServiceImpl"/>
|
<bean class="org.dspace.app.ldn.service.impl.NotifyServiceOutboundPatternServiceImpl"/>
|
||||||
<bean class="org.dspace.app.ldn.service.impl.LDNMessageServiceImpl"/>
|
<bean class="org.dspace.app.ldn.service.impl.LDNMessageServiceImpl"/>
|
||||||
<bean class="org.dspace.app.ldn.service.impl.NotifyPatternToTriggerImpl"/>
|
<bean class="org.dspace.app.ldn.service.impl.NotifyPatternToTriggerImpl"/>
|
||||||
<bean class="org.dspace.app.ldn.LDNBusinessDelegate"></bean>
|
|
||||||
|
|
||||||
<bean name="ldnRouter" class="org.dspace.app.ldn.LDNRouter">
|
<bean name="ldnRouter" class="org.dspace.app.ldn.LDNRouter">
|
||||||
<property name="processors">
|
<property name="incomingProcessors">
|
||||||
<map key-type="java.util.Set" value-type="org.dspace.app.ldn.LDNProcessor">
|
<map key-type="java.util.Set" value-type="org.dspace.app.ldn.LDNProcessor">
|
||||||
<entry>
|
<entry>
|
||||||
<key>
|
<key>
|
||||||
@@ -52,7 +51,7 @@
|
|||||||
<value>coar-notify:ReviewAction</value>
|
<value>coar-notify:ReviewAction</value>
|
||||||
</set>
|
</set>
|
||||||
</key>
|
</key>
|
||||||
<ref bean="acceptReviewAction" />
|
<ref bean="acceptAckAction" />
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<key>
|
<key>
|
||||||
@@ -61,7 +60,43 @@
|
|||||||
<value>coar-notify:ReviewAction</value>
|
<value>coar-notify:ReviewAction</value>
|
||||||
</set>
|
</set>
|
||||||
</key>
|
</key>
|
||||||
<ref bean="rejectReviewAction" />
|
<ref bean="rejectAckAction" />
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<key>
|
||||||
|
<set>
|
||||||
|
<value>Accept</value>
|
||||||
|
<value>coar-notify:EndorsementAction</value>
|
||||||
|
</set>
|
||||||
|
</key>
|
||||||
|
<ref bean="acceptAckAction" />
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<key>
|
||||||
|
<set>
|
||||||
|
<value>Reject</value>
|
||||||
|
<value>coar-notify:EndorsementAction</value>
|
||||||
|
</set>
|
||||||
|
</key>
|
||||||
|
<ref bean="rejectAckAction" />
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<key>
|
||||||
|
<set>
|
||||||
|
<value>Accept</value>
|
||||||
|
<value>coar-notify:IngestAction</value>
|
||||||
|
</set>
|
||||||
|
</key>
|
||||||
|
<ref bean="acceptAckAction" />
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<key>
|
||||||
|
<set>
|
||||||
|
<value>Reject</value>
|
||||||
|
<value>coar-notify:IngestAction</value>
|
||||||
|
</set>
|
||||||
|
</key>
|
||||||
|
<ref bean="rejectAckAction" />
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<key>
|
<key>
|
||||||
@@ -101,6 +136,37 @@
|
|||||||
</entry>
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="outcomingProcessors">
|
||||||
|
<map key-type="java.util.Set" value-type="org.dspace.app.ldn.LDNProcessor">
|
||||||
|
<entry>
|
||||||
|
<key>
|
||||||
|
<set>
|
||||||
|
<value>Offer</value>
|
||||||
|
<value>coar-notify:ReviewAction</value>
|
||||||
|
</set>
|
||||||
|
</key>
|
||||||
|
<ref bean="outcomingAnnounceReviewAction" />
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<key>
|
||||||
|
<set>
|
||||||
|
<value>Offer</value>
|
||||||
|
<value>coar-notify:EndorsementAction</value>
|
||||||
|
</set>
|
||||||
|
</key>
|
||||||
|
<ref bean="outcomingAnnounceEndorsementAction" />
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<key>
|
||||||
|
<set>
|
||||||
|
<value>Offer</value>
|
||||||
|
<value>coar-notify:IngestAction</value>
|
||||||
|
</set>
|
||||||
|
</key>
|
||||||
|
<ref bean="outcomingAnnounceIngestAction" />
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean name="offerEndorsementAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
|
<bean name="offerEndorsementAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
|
||||||
@@ -140,7 +206,7 @@
|
|||||||
<property name="actions">
|
<property name="actions">
|
||||||
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
||||||
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
||||||
<property name="actionSendFilter" value="william_welling@harvard.edu" />
|
<property name="actionSendFilter" value="${ldn.notification.email}" />
|
||||||
<property name="actionSendEmailTextFile" value="coar_notify_reviewed" />
|
<property name="actionSendEmailTextFile" value="coar_notify_reviewed" />
|
||||||
</bean>
|
</bean>
|
||||||
<bean class="org.dspace.app.ldn.action.LDNCorrectionAction">
|
<bean class="org.dspace.app.ldn.action.LDNCorrectionAction">
|
||||||
@@ -154,7 +220,7 @@
|
|||||||
<property name="actions">
|
<property name="actions">
|
||||||
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
||||||
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
||||||
<property name="actionSendFilter" value="william_welling@harvard.edu" />
|
<property name="actionSendFilter" value="${ldn.notification.email}" />
|
||||||
<property name="actionSendEmailTextFile" value="coar_notify_endorsed" />
|
<property name="actionSendEmailTextFile" value="coar_notify_endorsed" />
|
||||||
</bean>
|
</bean>
|
||||||
<bean class="org.dspace.app.ldn.action.LDNCorrectionAction">
|
<bean class="org.dspace.app.ldn.action.LDNCorrectionAction">
|
||||||
@@ -164,82 +230,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean name="acceptReviewAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
|
<bean name="acceptAckAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
|
||||||
<property name="changes">
|
|
||||||
<list value-type="org.dspace.app.ldn.processor.LDNMetadataChange">
|
|
||||||
<bean class="org.dspace.app.ldn.processor.LDNMetadataRemove">
|
|
||||||
<property name="qualifiers">
|
|
||||||
<list value-type="java.lang.String">
|
|
||||||
<value>requestreview</value>
|
|
||||||
<value>refused</value>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="valueTemplates">
|
|
||||||
<list value-type="java.lang.String">
|
|
||||||
<value>$LDNUtils.removedProtocol($notification.origin.id)</value>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
<bean class="org.dspace.app.ldn.processor.LDNMetadataRemove">
|
|
||||||
<property name="conditionTemplate" value="$StringUtils.isNotEmpty($notification.inReplyTo)" />
|
|
||||||
<property name="qualifiers">
|
|
||||||
<list value-type="java.lang.String">
|
|
||||||
<value>refused</value>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="valueTemplates">
|
|
||||||
<list value-type="java.lang.String">
|
|
||||||
<value>$LDNUtils.removedProtocol($notification.origin.id)</value>
|
|
||||||
<value>$notification.inReplyTo</value>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
<bean class="org.dspace.app.ldn.processor.LDNMetadataAdd">
|
|
||||||
<property name="conditionTemplate" value="$StringUtils.isNotEmpty($notification.inReplyTo)" />
|
|
||||||
<property name="qualifier" value="examination" />
|
|
||||||
<property name="valueTemplate" value="$timestamp||$LDNUtils.removedProtocol($notification.origin.id)||$notification.inReplyTo" />
|
|
||||||
</bean>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="actions">
|
<property name="actions">
|
||||||
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
||||||
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
||||||
<property name="actionSendFilter" value="william_welling@harvard.edu" />
|
<property name="actionSendFilter" value="${ldn.notification.email}" />
|
||||||
<property name="actionSendEmailTextFile" value="coar_notify_accepted" />
|
<property name="actionSendEmailTextFile" value="coar_notify_accepted" />
|
||||||
</bean>
|
</bean>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean name="rejectReviewAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
|
<bean name="rejectAckAction" class="org.dspace.app.ldn.processor.LDNMetadataProcessor">
|
||||||
<property name="changes">
|
|
||||||
<list value-type="org.dspace.app.ldn.processor.LDNMetadataChange">
|
|
||||||
<bean class="org.dspace.app.ldn.processor.LDNMetadataRemove">
|
|
||||||
<property name="conditionTemplate" value="$StringUtils.isNotEmpty($notification.inReplyTo)" />
|
|
||||||
<property name="qualifiers">
|
|
||||||
<list value-type="java.lang.String">
|
|
||||||
<value>examination</value>
|
|
||||||
<value>requestreview</value>
|
|
||||||
<value>requestendorsement</value>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="valueTemplates">
|
|
||||||
<list value-type="java.lang.String">
|
|
||||||
<value>$LDNUtils.removedProtocol($notification.origin.id)</value>
|
|
||||||
<value>$notification.inReplyTo</value>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
<bean class="org.dspace.app.ldn.processor.LDNMetadataAdd">
|
|
||||||
<property name="qualifier" value="refused" />
|
|
||||||
<property name="valueTemplate" value="$timestamp||$LDNUtils.removedProtocol($notification.origin.id)||$notification.inReplyTo" />
|
|
||||||
</bean>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
<property name="actions">
|
<property name="actions">
|
||||||
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
||||||
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
||||||
<property name="actionSendFilter" value="william_welling@harvard.edu" />
|
<property name="actionSendFilter" value="${ldn.notification.email}" />
|
||||||
<property name="actionSendEmailTextFile" value="coar_notify_rejected" />
|
<property name="actionSendEmailTextFile" value="coar_notify_rejected" />
|
||||||
</bean>
|
</bean>
|
||||||
</list>
|
</list>
|
||||||
@@ -250,7 +256,7 @@
|
|||||||
<property name="actions">
|
<property name="actions">
|
||||||
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
<list value-type="org.dspace.app.ldn.action.LDNAction">
|
||||||
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
<bean class="org.dspace.app.ldn.action.LDNEmailAction">
|
||||||
<property name="actionSendFilter" value="william_welling@harvard.edu" />
|
<property name="actionSendFilter" value="${ldn.notification.email}" />
|
||||||
<property name="actionSendEmailTextFile" value="coar_notify_relationship" />
|
<property name="actionSendEmailTextFile" value="coar_notify_relationship" />
|
||||||
</bean>
|
</bean>
|
||||||
<bean class="org.dspace.app.ldn.action.LDNCorrectionAction">
|
<bean class="org.dspace.app.ldn.action.LDNCorrectionAction">
|
||||||
@@ -260,4 +266,28 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean name="outcomingAnnounceReviewAction" 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.SendLDNMessageAction"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="outcomingAnnounceEndorsementAction" 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.SendLDNMessageAction"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean name="outcomingAnnounceIngestAction" 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.SendLDNMessageAction"/>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
Reference in New Issue
Block a user