Skip to content

Commit

Permalink
Merge branch 'DSpace:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
msevigny authored Feb 29, 2024
2 parents aa236f0 + 5b76b17 commit 280b501
Show file tree
Hide file tree
Showing 372 changed files with 22,868 additions and 1,338 deletions.
9 changes: 9 additions & 0 deletions dspace-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.5</version>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
Expand Down Expand Up @@ -837,6 +842,10 @@
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>
</exclusions>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema;
Expand All @@ -30,8 +32,6 @@
import org.dspace.content.service.MetadataFieldService;
import org.dspace.content.service.MetadataSchemaService;
import org.dspace.core.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
Expand All @@ -40,9 +40,9 @@
/**
* @author Richard Jones
*
* This class takes an xml document as passed in the arguments and
* This class takes an XML document as passed in the arguments and
* uses it to create metadata elements in the Metadata Registry if
* they do not already exist
* they do not already exist.
*
* The format of the XML file is as follows:
*
Expand All @@ -69,7 +69,7 @@ public class MetadataImporter {
/**
* logging category
*/
private static final Logger log = LoggerFactory.getLogger(MetadataImporter.class);
private static final Logger log = LogManager.getLogger();

/**
* Default constructor
Expand All @@ -89,6 +89,7 @@ private MetadataImporter() { }
* @throws SAXException if parser error
* @throws NonUniqueMetadataException if duplicate metadata
* @throws RegistryImportException if import fails
* @throws XPathExpressionException passed through
**/
public static void main(String[] args)
throws ParseException, SQLException, IOException, TransformerException,
Expand Down Expand Up @@ -125,6 +126,7 @@ public static void main(String[] args)
* @throws SAXException if parser error
* @throws NonUniqueMetadataException if duplicate metadata
* @throws RegistryImportException if import fails
* @throws XPathExpressionException passed through
*/
public static void loadRegistry(String file, boolean forceUpdate)
throws SQLException, IOException, TransformerException, ParserConfigurationException, AuthorizeException,
Expand Down Expand Up @@ -203,7 +205,7 @@ private static void loadSchema(Context context, Node node, boolean updateExistin

if (s == null) {
// Schema does not exist - create
log.info("Registering Schema " + name + " (" + namespace + ")");
log.info("Registering Schema {}({})", name, namespace);
metadataSchemaService.create(context, name, namespace);
} else {
// Schema exists - if it's the same namespace, allow the type imports to continue
Expand All @@ -215,7 +217,7 @@ private static void loadSchema(Context context, Node node, boolean updateExistin
// It's a different namespace - have we been told to update?
if (updateExisting) {
// Update the existing schema namespace and continue to type import
log.info("Updating Schema " + name + ": New namespace " + namespace);
log.info("Updating Schema {}: New namespace {}", name, namespace);
s.setNamespace(namespace);
metadataSchemaService.update(context, s);
} else {
Expand Down Expand Up @@ -274,7 +276,7 @@ private static void loadType(Context context, Node node)
if (qualifier == null) {
fieldName = schema + "." + element;
}
log.info("Registering metadata field " + fieldName);
log.info("Registering metadata field {}", fieldName);
MetadataField field = metadataFieldService.create(context, schemaObj, element, qualifier, scopeNote);
metadataFieldService.update(context, field);
}
Expand Down
30 changes: 30 additions & 0 deletions dspace-api/src/main/java/org/dspace/app/ldn/ItemFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.ldn;

/**
* model class for the item filters configured into item-filters.xml
*
* @author Mohamed Eskander (mohamed.eskander at 4science.com)
*/
public class ItemFilter {

private String id;

public ItemFilter(String id) {
this.id = id;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}
}
231 changes: 231 additions & 0 deletions dspace-api/src/main/java/org/dspace/app/ldn/LDNMessageConsumer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/**
* 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.app.ldn.service.NotifyServiceInboundPatternService;
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.logic.LogicalStatement;
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.utils.DSpace;
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 NotifyServiceInboundPatternService inboundPatternService;
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();
inboundPatternService = NotifyServiceFactory.getInstance().getNotifyServiceInboundPatternService();
}

@Override
public void consume(Context context, Event event) throws Exception {

if (event.getSubjectType() != Constants.ITEM ||
event.getEventType() != Event.INSTALL) {
return;
}

Item item = (Item) event.getSubject(context);
createManualLDNMessages(context, item);
createAutomaticLDNMessages(context, item);
}

private void createManualLDNMessages(Context context, Item item) throws SQLException, JsonProcessingException {
List<NotifyPatternToTrigger> patternsToTrigger =
notifyPatternToTriggerService.findByItem(context, item);

for (NotifyPatternToTrigger patternToTrigger : patternsToTrigger) {
createLDNMessage(context,patternToTrigger.getItem(),
patternToTrigger.getNotifyService(), patternToTrigger.getPattern());
}
}

private void createAutomaticLDNMessages(Context context, Item item) throws SQLException, JsonProcessingException {

List<NotifyServiceInboundPattern> inboundPatterns = inboundPatternService.findAutomaticPatterns(context);

for (NotifyServiceInboundPattern inboundPattern : inboundPatterns) {
if (StringUtils.isEmpty(inboundPattern.getConstraint()) ||
evaluateFilter(context, item, inboundPattern.getConstraint())) {
createLDNMessage(context, item, inboundPattern.getNotifyService(), inboundPattern.getPattern());
}
}
}

private boolean evaluateFilter(Context context, Item item, String constraint) {
LogicalStatement filter =
new DSpace().getServiceManager().getServiceByName(constraint, LogicalStatement.class);

return filter != null && filter.getResult(context, item);
}

private void createLDNMessage(Context context, Item item, NotifyServiceEntity service, String pattern)
throws SQLException, JsonMappingException, JsonProcessingException {

LDN ldn = getLDNMessage(pattern);
LDNMessageEntity ldnMessage =
ldnMessageService.create(context, format("urn:uuid:%s", UUID.randomUUID()));

ldnMessage.setObject(item);
ldnMessage.setTarget(service);
ldnMessage.setQueueStatus(LDNMessageEntity.QUEUE_STATUS_QUEUED);
ldnMessage.setQueueTimeout(new Date());

appendGeneratedMessage(ldn, ldnMessage, pattern);

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 {

}

}
Loading

0 comments on commit 280b501

Please sign in to comment.