Skip to content

Commit

Permalink
Merge pull request DSpace#8926 from amgciadev/pr-8923-b
Browse files Browse the repository at this point in the history
OAI: add support to extract embargo from bitstreams
  • Loading branch information
tdonohue authored Sep 22, 2023
2 parents 7eedb12 + 3225544 commit 96ba071
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,21 @@ public interface AccessStatusHelper {
*
* @param context the DSpace context
* @param item the item
* @param threshold the embargo threshold date
* @return an access status value
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
public String getAccessStatusFromItem(Context context, Item item, Date threshold)
throws SQLException;

/**
* Retrieve embargo information for the item
*
* @param context the DSpace context
* @param item the item to check for embargo information
* @param threshold the embargo threshold date
* @return an embargo date
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
public String getEmbargoFromItem(Context context, Item item, Date threshold) throws SQLException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,9 @@ public void init() throws Exception {
public String getAccessStatus(Context context, Item item) throws SQLException {
return helper.getAccessStatusFromItem(context, item, forever_date);
}

@Override
public String getEmbargoFromItem(Context context, Item item) throws SQLException {
return helper.getEmbargoFromItem(context, item, forever_date);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,19 @@
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.joda.time.LocalDate;

/**
* Default plugin implementation of the access status helper.
* The getAccessStatusFromItem method provides a simple logic to
* calculate the access status of an item based on the policies of
* the primary or the first bitstream in the original bundle.
* Users can override this method for enhanced functionality.
*
* The getEmbargoInformationFromItem method provides a simple logic to
* * retrieve embargo information of bitstreams from an item based on the policies of
* * the primary or the first bitstream in the original bundle.
* * Users can override this method for enhanced functionality.
*/
public class DefaultAccessStatusHelper implements AccessStatusHelper {
public static final String EMBARGO = "embargo";
Expand All @@ -54,12 +60,12 @@ public DefaultAccessStatusHelper() {

/**
* Look at the item's policies to determine an access status value.
* It is also considering a date threshold for embargos and restrictions.
* It is also considering a date threshold for embargoes and restrictions.
*
* If the item is null, simply returns the "unknown" value.
*
* @param context the DSpace context
* @param item the item to embargo
* @param item the item to check for embargoes
* @param threshold the embargo threshold date
* @return an access status value
*/
Expand All @@ -86,7 +92,7 @@ public String getAccessStatusFromItem(Context context, Item item, Date threshold
.findFirst()
.orElse(null);
}
return caculateAccessStatusForDso(context, bitstream, threshold);
return calculateAccessStatusForDso(context, bitstream, threshold);
}

/**
Expand All @@ -104,7 +110,7 @@ public String getAccessStatusFromItem(Context context, Item item, Date threshold
* @param threshold the embargo threshold date
* @return an access status value
*/
private String caculateAccessStatusForDso(Context context, DSpaceObject dso, Date threshold)
private String calculateAccessStatusForDso(Context context, DSpaceObject dso, Date threshold)
throws SQLException {
if (dso == null) {
return METADATA_ONLY;
Expand Down Expand Up @@ -156,4 +162,87 @@ private String caculateAccessStatusForDso(Context context, DSpaceObject dso, Dat
}
return RESTRICTED;
}

/**
* Look at the policies of the primary (or first) bitstream of the item to retrieve its embargo.
*
* If the item is null, simply returns an empty map with no embargo information.
*
* @param context the DSpace context
* @param item the item to embargo
* @return an access status value
*/
@Override
public String getEmbargoFromItem(Context context, Item item, Date threshold)
throws SQLException {
Date embargoDate;

// If Item status is not "embargo" then return a null embargo date.
String accessStatus = getAccessStatusFromItem(context, item, threshold);

if (item == null || !accessStatus.equals(EMBARGO)) {
return null;
}
// Consider only the original bundles.
List<Bundle> bundles = item.getBundles(Constants.DEFAULT_BUNDLE_NAME);
// Check for primary bitstreams first.
Bitstream bitstream = bundles.stream()
.map(bundle -> bundle.getPrimaryBitstream())
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
if (bitstream == null) {
// If there is no primary bitstream,
// take the first bitstream in the bundles.
bitstream = bundles.stream()
.map(bundle -> bundle.getBitstreams())
.flatMap(List::stream)
.findFirst()
.orElse(null);
}

if (bitstream == null) {
return null;
}

embargoDate = this.retrieveShortestEmbargo(context, bitstream);

return embargoDate != null ? embargoDate.toString() : null;
}

/**
*
*/
private Date retrieveShortestEmbargo(Context context, Bitstream bitstream) throws SQLException {
Date embargoDate = null;
// Only consider read policies.
List<ResourcePolicy> policies = authorizeService
.getPoliciesActionFilter(context, bitstream, Constants.READ);

// Looks at all read policies.
for (ResourcePolicy policy : policies) {
boolean isValid = resourcePolicyService.isDateValid(policy);
Group group = policy.getGroup();

if (group != null && StringUtils.equals(group.getName(), Group.ANONYMOUS)) {
// Only calculate the status for the anonymous group.
if (!isValid) {
// If the policy is not valid there is an active embargo
Date startDate = policy.getStartDate();

if (startDate != null && !startDate.before(LocalDate.now().toDate())) {
// There is an active embargo: aim to take the shortest embargo (account for rare cases where
// more than one resource policy exists)
if (embargoDate == null) {
embargoDate = startDate;
} else {
embargoDate = startDate.before(embargoDate) ? startDate : embargoDate;
}
}
}
}
}

return embargoDate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,18 @@ public interface AccessStatusService {
*
* @param context the DSpace context
* @param item the item
* @return an access status value
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
public String getAccessStatus(Context context, Item item) throws SQLException;

/**
* Retrieve embargo information for the item
*
* @param context the DSpace context
* @param item the item to check for embargo information
* @return an embargo date
* @throws SQLException An exception that provides information on a database access error or other errors.
*/
public String getEmbargoFromItem(Context context, Item item) throws SQLException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ public void testWithEmbargo() throws Exception {
context.restoreAuthSystemState();
String status = helper.getAccessStatusFromItem(context, itemWithEmbargo, threshold);
assertThat("testWithEmbargo 0", status, equalTo(DefaultAccessStatusHelper.EMBARGO));
String embargoDate = helper.getEmbargoFromItem(context, itemWithEmbargo, threshold);
assertThat("testWithEmbargo 1", embargoDate, equalTo(policy.getStartDate().toString()));
}

/**
Expand Down Expand Up @@ -391,6 +393,8 @@ public void testWithPrimaryAndMultipleBitstreams() throws Exception {
context.restoreAuthSystemState();
String status = helper.getAccessStatusFromItem(context, itemWithPrimaryAndMultipleBitstreams, threshold);
assertThat("testWithPrimaryAndMultipleBitstreams 0", status, equalTo(DefaultAccessStatusHelper.EMBARGO));
String embargoDate = helper.getEmbargoFromItem(context, itemWithPrimaryAndMultipleBitstreams, threshold);
assertThat("testWithPrimaryAndMultipleBitstreams 1", embargoDate, equalTo(policy.getStartDate().toString()));
}

/**
Expand Down Expand Up @@ -420,6 +424,8 @@ public void testWithNoPrimaryAndMultipleBitstreams() throws Exception {
context.restoreAuthSystemState();
String status = helper.getAccessStatusFromItem(context, itemWithoutPrimaryAndMultipleBitstreams, threshold);
assertThat("testWithNoPrimaryAndMultipleBitstreams 0", status, equalTo(DefaultAccessStatusHelper.OPEN_ACCESS));
String embargoDate = helper.getEmbargoFromItem(context, itemWithEmbargo, threshold);
assertThat("testWithNoPrimaryAndMultipleBitstreams 1", embargoDate, equalTo(null));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import com.lyncode.xoai.dataprovider.xml.xoai.Element;
import com.lyncode.xoai.dataprovider.xml.xoai.Metadata;
import org.apache.commons.lang3.StringUtils;
import org.dspace.access.status.factory.AccessStatusServiceFactory;
import org.dspace.access.status.service.AccessStatusService;
import org.dspace.content.Item;
Expand All @@ -31,6 +32,13 @@
* <field name="value">open.access</field>
* </element>
* </element>
* OR
* <element name="others">
* <element name="access-status">
* <field name="value">embargo</field>
* <field name="embargo">2024-10-10</field>
* </element>
* </element>
* }
* </pre>
* Returning Values are based on:
Expand All @@ -46,9 +54,15 @@ public Metadata additionalMetadata(Context context, Metadata metadata, Item item
String accessStatusType;
accessStatusType = accessStatusService.getAccessStatus(context, item);

String embargoFromItem = accessStatusService.getEmbargoFromItem(context, item);

Element accessStatus = ItemUtils.create("access-status");
accessStatus.getField().add(ItemUtils.createValue("value", accessStatusType));

if (StringUtils.isNotEmpty(embargoFromItem)) {
accessStatus.getField().add(ItemUtils.createValue("embargo", embargoFromItem));
}

Element others;
List<Element> elements = metadata.getElement();
if (ItemUtils.getElement(elements, "others") != null) {
Expand Down
14 changes: 14 additions & 0 deletions dspace/config/crosswalks/oai/metadataFormats/uketd_dc.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@
<!-- <dc:identifier xsi:type="dcterms:URI"><xsl:value-of select="." /></dc:identifier> -->
</xsl:for-each>

<!-- ******* Check access-status information to determine the item's access status ******* -->
<xsl:for-each select="doc:metadata/doc:element[@name='others']/doc:element[@name='access-status']/doc:field[@name='value']/text()">
<!-- Add access status information for embargo or restricted status only in uketdterms:embargotype -->
<xsl:if test=".='restricted' or .='embargo'">
<uketdterms:embargotype><xsl:value-of select="." /></uketdterms:embargotype>
</xsl:if>
</xsl:for-each>

<!-- ******* Check access-status embargo information for embargoed content associated with this item ******* -->
<xsl:for-each select="doc:metadata/doc:element[@name='others']/doc:element[@name='access-status']/doc:field[@name='embargo']/text()">
<!-- Add embargo information -->
<uketdterms:embargodate><xsl:value-of select="." /></uketdterms:embargodate>
</xsl:for-each>

<!-- ******* URLs for digital object(s) (obtained from file 'bundles') ******* -->
<xsl:for-each select="doc:metadata/doc:element[@name='bundles']/doc:element[@name='bundle']">

Expand Down

0 comments on commit 96ba071

Please sign in to comment.