Skip to content

Commit 895926f

Browse files
committed
Refactored access-status to include embargo date based on the DefaultAccessStatusHelper logic (look at primary or first bitstream)
1 parent baab5ac commit 895926f

7 files changed

Lines changed: 139 additions & 9 deletions

File tree

dspace-api/src/main/java/org/dspace/access/status/AccessStatusHelper.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,14 @@ public interface AccessStatusHelper {
2727
*/
2828
public String getAccessStatusFromItem(Context context, Item item, Date threshold)
2929
throws SQLException;
30+
31+
/**
32+
* Retrieve embargo information for the item
33+
*
34+
* @param context the DSpace context
35+
* @param item the item to check for embargo information
36+
* @return an embargo date
37+
* @throws SQLException An exception that provides information on a database access error or other errors.
38+
*/
39+
public String getEmbargoFromItem(Context context, Item item) throws SQLException;
3040
}

dspace-api/src/main/java/org/dspace/access/status/AccessStatusServiceImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,9 @@ public void init() throws Exception {
6363
public String getAccessStatus(Context context, Item item) throws SQLException {
6464
return helper.getAccessStatusFromItem(context, item, forever_date);
6565
}
66+
67+
@Override
68+
public String getEmbargoFromItem(Context context, Item item) throws SQLException {
69+
return helper.getEmbargoFromItem(context, item);
70+
}
6671
}

dspace-api/src/main/java/org/dspace/access/status/DefaultAccessStatusHelper.java

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,19 @@
2626
import org.dspace.core.Constants;
2727
import org.dspace.core.Context;
2828
import org.dspace.eperson.Group;
29+
import org.joda.time.LocalDate;
2930

3031
/**
3132
* Default plugin implementation of the access status helper.
3233
* The getAccessStatusFromItem method provides a simple logic to
3334
* calculate the access status of an item based on the policies of
3435
* the primary or the first bitstream in the original bundle.
3536
* Users can override this method for enhanced functionality.
37+
*
38+
* The getEmbargoInformationFromItem method provides a simple logic to
39+
* * retrieve embargo information of bitstreams from an item based on the policies of
40+
* * the primary or the first bitstream in the original bundle.
41+
* * Users can override this method for enhanced functionality.
3642
*/
3743
public class DefaultAccessStatusHelper implements AccessStatusHelper {
3844
public static final String EMBARGO = "embargo";
@@ -54,12 +60,12 @@ public DefaultAccessStatusHelper() {
5460

5561
/**
5662
* Look at the item's policies to determine an access status value.
57-
* It is also considering a date threshold for embargos and restrictions.
63+
* It is also considering a date threshold for embargoes and restrictions.
5864
*
5965
* If the item is null, simply returns the "unknown" value.
6066
*
6167
* @param context the DSpace context
62-
* @param item the item to embargo
68+
* @param item the item to check for embargoes
6369
* @param threshold the embargo threshold date
6470
* @return an access status value
6571
*/
@@ -86,7 +92,7 @@ public String getAccessStatusFromItem(Context context, Item item, Date threshold
8692
.findFirst()
8793
.orElse(null);
8894
}
89-
return caculateAccessStatusForDso(context, bitstream, threshold);
95+
return calculateAccessStatusForDso(context, bitstream, threshold);
9096
}
9197

9298
/**
@@ -104,7 +110,7 @@ public String getAccessStatusFromItem(Context context, Item item, Date threshold
104110
* @param threshold the embargo threshold date
105111
* @return an access status value
106112
*/
107-
private String caculateAccessStatusForDso(Context context, DSpaceObject dso, Date threshold)
113+
private String calculateAccessStatusForDso(Context context, DSpaceObject dso, Date threshold)
108114
throws SQLException {
109115
if (dso == null) {
110116
return METADATA_ONLY;
@@ -156,4 +162,79 @@ private String caculateAccessStatusForDso(Context context, DSpaceObject dso, Dat
156162
}
157163
return RESTRICTED;
158164
}
165+
166+
/**
167+
* Look at the policies of the primary (or first) bitstream of the item to retrieve its embargo.
168+
*
169+
* If the item is null, simply returns an empty map with no embargo information.
170+
*
171+
* @param context the DSpace context
172+
* @param item the item to embargo
173+
* @return an access status value
174+
*/
175+
@Override
176+
public String getEmbargoFromItem(Context context, Item item)
177+
throws SQLException {
178+
Date embargoDate;
179+
180+
if (item == null) {
181+
return null;
182+
}
183+
// Consider only the original bundles.
184+
List<Bundle> bundles = item.getBundles(Constants.DEFAULT_BUNDLE_NAME);
185+
// Check for primary bitstreams first.
186+
Bitstream bitstream = bundles.stream()
187+
.map(bundle -> bundle.getPrimaryBitstream())
188+
.filter(Objects::nonNull)
189+
.findFirst()
190+
.orElse(null);
191+
if (bitstream == null) {
192+
// If there is no primary bitstream,
193+
// take the first bitstream in the bundles.
194+
bitstream = bundles.stream()
195+
.map(bundle -> bundle.getBitstreams())
196+
.flatMap(List::stream)
197+
.findFirst()
198+
.orElse(null);
199+
}
200+
201+
embargoDate = this.retrieveLongestEmbargo(context, bitstream);
202+
203+
return embargoDate != null ? embargoDate.toString() : null;
204+
}
205+
206+
/**
207+
*
208+
*/
209+
private Date retrieveLongestEmbargo(Context context, Bitstream bitstream) throws SQLException {
210+
Date embargoDate = null;
211+
// Only consider read policies.
212+
List<ResourcePolicy> policies = authorizeService
213+
.getPoliciesActionFilter(context, bitstream, Constants.READ);
214+
215+
// Looks at all read policies.
216+
for (ResourcePolicy policy : policies) {
217+
boolean isValid = resourcePolicyService.isDateValid(policy);
218+
Group group = policy.getGroup();
219+
220+
if (group != null && StringUtils.equals(group.getName(), Group.ANONYMOUS)) {
221+
// Only calculate the status for the anonymous group.
222+
if (!isValid) {
223+
// If the policy is not valid there is an active embargo
224+
Date startDate = policy.getStartDate();
225+
226+
if (startDate != null && !startDate.before(LocalDate.now().toDate())) {
227+
// There is an active embargo: aim to take the longest embargo
228+
if (embargoDate == null) {
229+
embargoDate = startDate;
230+
} else {
231+
embargoDate = startDate.after(embargoDate) ? startDate : embargoDate;
232+
}
233+
}
234+
}
235+
}
236+
}
237+
238+
return embargoDate;
239+
}
159240
}

dspace-api/src/main/java/org/dspace/access/status/service/AccessStatusService.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package org.dspace.access.status.service;
99

1010
import java.sql.SQLException;
11+
import java.util.Date;
1112

1213
import org.dspace.content.Item;
1314
import org.dspace.core.Context;
@@ -40,7 +41,18 @@ public interface AccessStatusService {
4041
*
4142
* @param context the DSpace context
4243
* @param item the item
44+
* @return an access status value
4345
* @throws SQLException An exception that provides information on a database access error or other errors.
4446
*/
4547
public String getAccessStatus(Context context, Item item) throws SQLException;
48+
49+
/**
50+
* Retrieve embargo information for the item
51+
*
52+
* @param context the DSpace context
53+
* @param item the item to check for embargo information
54+
* @return an embargo date
55+
* @throws SQLException An exception that provides information on a database access error or other errors.
56+
*/
57+
public String getEmbargoFromItem(Context context, Item item) throws SQLException;
4658
}

dspace-api/src/test/java/org/dspace/access/status/DefaultAccessStatusHelperTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package org.dspace.access.status;
99

1010
import static org.hamcrest.CoreMatchers.equalTo;
11+
import static org.hamcrest.CoreMatchers.notNullValue;
1112
import static org.hamcrest.MatcherAssert.assertThat;
1213
import static org.junit.Assert.fail;
1314

@@ -273,6 +274,8 @@ public void testWithEmbargo() throws Exception {
273274
context.restoreAuthSystemState();
274275
String status = helper.getAccessStatusFromItem(context, itemWithEmbargo, threshold);
275276
assertThat("testWithEmbargo 0", status, equalTo(DefaultAccessStatusHelper.EMBARGO));
277+
String embargoDate = helper.getEmbargoFromItem(context, itemWithEmbargo);
278+
assertThat("testWithEmbargo 1", embargoDate, equalTo(policy.getStartDate().toString()));
276279
}
277280

278281
/**
@@ -390,6 +393,8 @@ public void testWithPrimaryAndMultipleBitstreams() throws Exception {
390393
context.restoreAuthSystemState();
391394
String status = helper.getAccessStatusFromItem(context, itemWithPrimaryAndMultipleBitstreams, threshold);
392395
assertThat("testWithPrimaryAndMultipleBitstreams 0", status, equalTo(DefaultAccessStatusHelper.EMBARGO));
396+
String embargoDate = helper.getEmbargoFromItem(context, itemWithPrimaryAndMultipleBitstreams);
397+
assertThat("testWithPrimaryAndMultipleBitstreams 1", embargoDate, equalTo(policy.getStartDate().toString()));
393398
}
394399

395400
/**
@@ -419,5 +424,7 @@ public void testWithNoPrimaryAndMultipleBitstreams() throws Exception {
419424
context.restoreAuthSystemState();
420425
String status = helper.getAccessStatusFromItem(context, itemWithoutPrimaryAndMultipleBitstreams, threshold);
421426
assertThat("testWithNoPrimaryAndMultipleBitstreams 0", status, equalTo(DefaultAccessStatusHelper.OPEN_ACCESS));
427+
String embargoDate = helper.getEmbargoFromItem(context, itemWithEmbargo);
428+
assertThat("testWithNoPrimaryAndMultipleBitstreams 1", embargoDate, equalTo(null));
422429
}
423430
}

dspace-oai/src/main/java/org/dspace/xoai/app/plugins/AccessStatusElementItemCompilePlugin.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import com.lyncode.xoai.dataprovider.xml.xoai.Element;
1414
import com.lyncode.xoai.dataprovider.xml.xoai.Metadata;
15+
import org.apache.commons.lang3.StringUtils;
1516
import org.dspace.access.status.factory.AccessStatusServiceFactory;
1617
import org.dspace.access.status.service.AccessStatusService;
1718
import org.dspace.content.Item;
@@ -31,6 +32,13 @@
3132
* <field name="value">open.access</field>
3233
* </element>
3334
* </element>
35+
* OR
36+
* <element name="others">
37+
* <element name="access-status">
38+
* <field name="value">embargo</field>
39+
* <field name="embargo">2024-10-10</field>
40+
* </element>
41+
* </element>
3442
* }
3543
* </pre>
3644
* Returning Values are based on:
@@ -46,9 +54,15 @@ public Metadata additionalMetadata(Context context, Metadata metadata, Item item
4654
String accessStatusType;
4755
accessStatusType = accessStatusService.getAccessStatus(context, item);
4856

57+
String embargoFromItem = accessStatusService.getEmbargoFromItem(context, item);
58+
4959
Element accessStatus = ItemUtils.create("access-status");
5060
accessStatus.getField().add(ItemUtils.createValue("value", accessStatusType));
5161

62+
if (StringUtils.isNotEmpty(embargoFromItem)) {
63+
accessStatus.getField().add(ItemUtils.createValue("embargo", embargoFromItem));
64+
}
65+
5266
Element others;
5367
List<Element> elements = metadata.getElement();
5468
if (ItemUtils.getElement(elements, "others") != null) {

dspace/config/crosswalks/oai/metadataFormats/uketd_dc.xsl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@
115115
<!-- <dc:identifier xsi:type="dcterms:URI"><xsl:value-of select="." /></dc:identifier> -->
116116
</xsl:for-each>
117117

118+
<!-- ******* Check access-status embargo information for embargoed content associated with this item ******* -->
119+
<xsl:for-each select="doc:metadata/doc:element[@name='others']/doc:element[@name='access-status']/doc:field[@name='embargo']/text()">
120+
<!-- Add embargo information -->
121+
<uketdterms:embargodate><xsl:value-of select="." /></uketdterms:embargodate>
122+
</xsl:for-each>
123+
118124
<!-- ******* URLs for digital object(s) (obtained from file 'bundles') ******* -->
119125
<xsl:for-each select="doc:metadata/doc:element[@name='bundles']/doc:element[@name='bundle']">
120126

@@ -123,11 +129,6 @@
123129
<xsl:for-each select="doc:element[@name='bitstreams']/doc:element">
124130
<dc:identifier xsi:type="dcterms:URI"><xsl:value-of select="doc:field[@name='url']/text()" /></dc:identifier>
125131
<uketdterms:checksum xsi:type="uketdterms:MD5"><xsl:value-of select="doc:field[@name='checksum']/text()" /></uketdterms:checksum>
126-
<!-- Add embargo information -->
127-
<xsl:if test="ancestor::*/doc:field[@name='name']/text() = 'ORIGINAL'
128-
and doc:field[@name='embargo']/text()">
129-
<uketdterms:embargodate><xsl:value-of select="doc:field[@name='embargo']/text()" /></uketdterms:embargodate>
130-
</xsl:if>
131132
</xsl:for-each>
132133
</xsl:if>
133134

0 commit comments

Comments
 (0)