Skip to content

Commit c662a79

Browse files
Paurikova2jr-rk
andauthored
ZCU-PUB/New endpoint for embargo info (start_date & end_date) (#1046) (#1144)
* Added new endpoint for embargo resources, methods to find them and integration test * Edited tests * Unit tests fix: 5 checkstyle violations * Fix: consistency of find & count methods logic * Unit tests fix: 11 checkstyle violations * Added more valid parameter combinations & edited tests * Changed unused static class to void setup helper * Renamed endpoint and related methods to findByDate & countByDate * Changed documentation to be consistent * Removed trailing whitespace Co-authored-by: jurinecko <95219754+jr-rk@users.noreply.github.com>
1 parent fe366e1 commit c662a79

6 files changed

Lines changed: 341 additions & 0 deletions

File tree

dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ public ResourcePolicy find(Context context, int id) throws SQLException {
7878
return resourcePolicyDAO.findByID(context, ResourcePolicy.class, id);
7979
}
8080

81+
@Override
82+
public List<ResourcePolicy> findAll(Context context, int offset, int limit) throws SQLException {
83+
return resourcePolicyDAO.findAll(context, offset, limit);
84+
}
85+
86+
@Override
87+
public int countAll(Context context) throws SQLException {
88+
return resourcePolicyDAO.countAll(context);
89+
}
90+
8191
/**
8292
* Create a new ResourcePolicy
8393
*
@@ -426,6 +436,17 @@ public int countByGroupAndResourceUuid(Context context, Group group, UUID resour
426436
return resourcePolicyDAO.countByGroupAndResourceUuid(context, group, resourceUuid);
427437
}
428438

439+
@Override
440+
public List<ResourcePolicy> findByDate(Context context, Boolean hasStartDate, Boolean hasEndDate,
441+
int offset, int limit) throws SQLException {
442+
return resourcePolicyDAO.findByDate(context, hasStartDate, hasEndDate, offset, limit);
443+
}
444+
445+
@Override
446+
public int countByDate(Context context, Boolean hasStartDate, Boolean hasEndDate) throws SQLException {
447+
return resourcePolicyDAO.countByDate(context, hasStartDate, hasEndDate);
448+
}
449+
429450
@Override
430451
public boolean isMyResourcePolicy(Context context, EPerson eperson, Integer id) throws SQLException {
431452
boolean isMy = false;

dspace-api/src/main/java/org/dspace/authorize/dao/ResourcePolicyDAO.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,5 +242,48 @@ public List<ResourcePolicy> findByGroupAndResourceUuid(Context context, Group gr
242242

243243
public ResourcePolicy findOneById(Context context, Integer id) throws SQLException;
244244

245+
/**
246+
* Return a paginated list of all resource policies
247+
*
248+
* @param context DSpace context object
249+
* @param offset the position of the first result to return
250+
* @param limit paging limit
251+
* @return list of resource policies
252+
* @throws SQLException if database error
253+
*/
254+
public List<ResourcePolicy> findAll(Context context, int offset, int limit) throws SQLException;
245255

256+
/**
257+
* Count all the resource policies
258+
*
259+
* @param context DSpace context object
260+
* @return total resource policies
261+
* @throws SQLException if database error
262+
*/
263+
public int countAll(Context context) throws SQLException;
264+
265+
/**
266+
* Return a paginated list of policies based on embargo date presence criteria
267+
*
268+
* @param context DSpace context object
269+
* @param hasStartDate filter for start date presence, null=any, true=required, false=must be absent
270+
* @param hasEndDate filter for end date presence, null=any, true=required, false=must be absent
271+
* @param offset the position of the first result to return
272+
* @param limit paging limit
273+
* @return list of resource policies
274+
* @throws SQLException if database error
275+
*/
276+
public List<ResourcePolicy> findByDate(Context context, Boolean hasStartDate, Boolean hasEndDate,
277+
int offset, int limit) throws SQLException;
278+
279+
/**
280+
* Count all the resource policies based on embargo date presence criteria
281+
*
282+
* @param context DSpace context object
283+
* @param hasStartDate filter for start date presence, null=any, true=required, false=must be absent
284+
* @param hasEndDate filter for end date presence, null=any, true=required, false=must be absent
285+
* @return total policies
286+
* @throws SQLException if database error
287+
*/
288+
public int countByDate(Context context, Boolean hasStartDate, Boolean hasEndDate) throws SQLException;
246289
}

dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,4 +403,62 @@ public ResourcePolicy findOneById(Context context, Integer id) throws SQLExcepti
403403
criteriaQuery.where(criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.id), id));
404404
return singleResult(context, criteriaQuery);
405405
}
406+
407+
@Override
408+
public List<ResourcePolicy> findAll(Context context, int offset, int limit) throws SQLException {
409+
Query query = createQuery(context, "SELECT rp FROM ResourcePolicy rp ORDER BY rp.id");
410+
query.setFirstResult(offset);
411+
query.setMaxResults(limit);
412+
return list(query);
413+
}
414+
415+
@Override
416+
public int countAll(Context context) throws SQLException {
417+
Query query = createQuery(context, "SELECT count(rp.id) FROM ResourcePolicy rp");
418+
return count(query);
419+
}
420+
421+
/**
422+
* Helper to build the WHERE clause for date presence queries.
423+
*/
424+
private String buildDatePresenceWhere(Boolean hasStartDate, Boolean hasEndDate) {
425+
if (hasStartDate == null && hasEndDate == null) {
426+
return " WHERE rp.startDate IS NOT NULL OR rp.endDate IS NOT NULL";
427+
} else if (Boolean.TRUE.equals(hasStartDate) && Boolean.TRUE.equals(hasEndDate)) {
428+
return " WHERE rp.startDate IS NOT NULL AND rp.endDate IS NOT NULL";
429+
} else if (Boolean.TRUE.equals(hasStartDate) && hasEndDate == null) {
430+
return " WHERE rp.startDate IS NOT NULL";
431+
} else if (hasStartDate == null && Boolean.TRUE.equals(hasEndDate)) {
432+
return " WHERE rp.endDate IS NOT NULL";
433+
} else if (Boolean.TRUE.equals(hasStartDate) && Boolean.FALSE.equals(hasEndDate)) {
434+
return " WHERE rp.startDate IS NOT NULL AND rp.endDate IS NULL";
435+
} else if (Boolean.FALSE.equals(hasStartDate) && Boolean.TRUE.equals(hasEndDate)) {
436+
return " WHERE rp.startDate IS NULL AND rp.endDate IS NOT NULL";
437+
} else if (Boolean.FALSE.equals(hasStartDate) && Boolean.FALSE.equals(hasEndDate)) {
438+
return " WHERE rp.startDate IS NULL AND rp.endDate IS NULL";
439+
}
440+
return "";
441+
}
442+
443+
@Override
444+
public List<ResourcePolicy> findByDate(Context context, Boolean hasStartDate, Boolean hasEndDate,
445+
int offset, int limit) throws SQLException {
446+
StringBuilder queryBuilder = new StringBuilder("SELECT rp FROM ResourcePolicy rp");
447+
queryBuilder.append(buildDatePresenceWhere(hasStartDate, hasEndDate));
448+
queryBuilder.append(" ORDER BY rp.id");
449+
450+
Query query = createQuery(context, queryBuilder.toString());
451+
query.setFirstResult(offset);
452+
query.setMaxResults(limit);
453+
454+
return list(query);
455+
}
456+
457+
@Override
458+
public int countByDate(Context context, Boolean hasStartDate, Boolean hasEndDate) throws SQLException {
459+
StringBuilder queryBuilder = new StringBuilder("SELECT count(rp.id) FROM ResourcePolicy rp");
460+
queryBuilder.append(buildDatePresenceWhere(hasStartDate, hasEndDate));
461+
Query query = createQuery(context, queryBuilder.toString());
462+
return count(query);
463+
}
406464
}

dspace-api/src/main/java/org/dspace/authorize/service/ResourcePolicyService.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,26 @@ public interface ResourcePolicyService {
3131

3232
public ResourcePolicy find(Context context, int id) throws SQLException;
3333

34+
/**
35+
* Finds all ResourcePolicies in the database with pagination.
36+
*
37+
* @param context The relevant DSpace Context.
38+
* @param offset The number of records to skip.
39+
* @param limit The number of records to retrieve.
40+
* @return A list of ResourcePolicy objects.
41+
* @throws SQLException If a database error occurs.
42+
*/
43+
public List<ResourcePolicy> findAll(Context context, int offset, int limit) throws SQLException;
44+
45+
/**
46+
* Counts the total number of ResourcePolicies in the database.
47+
*
48+
* @param context The relevant DSpace Context.
49+
* @return The total number of policies.
50+
* @throws SQLException If a database error occurs.
51+
*/
52+
public int countAll(Context context) throws SQLException;
53+
3454
/**
3555
* Persist a model object.
3656
*
@@ -300,6 +320,31 @@ public List<ResourcePolicy> findByGroupAndResourceUuid(Context context, Group gr
300320
*/
301321
public int countByGroupAndResourceUuid(Context context, Group group, UUID resourceUuid) throws SQLException;
302322

323+
/**
324+
* Return a paginated list of policies based on embargo date presence criteria
325+
*
326+
* @param context DSpace context object
327+
* @param hasStartDate filter for start date presence, null=any, true=required, false=must be absent
328+
* @param hasEndDate filter for end date presence, null=any, true=required, false=must be absent
329+
* @param offset the position of the first result to return
330+
* @param limit paging limit
331+
* @return list of resource policies
332+
* @throws SQLException if database error
333+
*/
334+
public List<ResourcePolicy> findByDate(Context context, Boolean hasStartDate, Boolean hasEndDate,
335+
int offset, int limit) throws SQLException;
336+
337+
/**
338+
* Count all the resource policies based on embargo date presence criteria
339+
*
340+
* @param context DSpace context object
341+
* @param hasStartDate filter for start date presence, null=any, true=required, false=must be absent
342+
* @param hasEndDate filter for end date presence, null=any, true=required, false=must be absent
343+
* @return total policies
344+
* @throws SQLException if database error
345+
*/
346+
public int countByDate(Context context, Boolean hasStartDate, Boolean hasEndDate) throws SQLException;
347+
303348
/**
304349
* Check if the resource policy identified with (id) belong to ePerson
305350
*

dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ResourcePolicyRestRepository.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,37 @@ public Page<ResourcePolicyRest> findByGroup(@Parameter(value = "uuid", required
233233
return converter.toRestPage(resourcePolisies, pageable, total, utils.obtainProjection());
234234
}
235235

236+
/**
237+
* Find the resource policies matching embargo date presence criteria
238+
*
239+
* @param hasStartDate optional, filter for start date presence
240+
* @param hasEndDate optional, filter for end date presence
241+
* @param pageable contains the pagination information
242+
* @return a Page of ResourcePolicyRest instances matching the embargo criteria
243+
*/
244+
@PreAuthorize("hasAuthority('ADMIN')")
245+
@SearchRestMethod(name = "embargo")
246+
public Page<ResourcePolicyRest> findByDate(
247+
@Parameter(value = "hasStartDate", required = false) Boolean hasStartDate,
248+
@Parameter(value = "hasEndDate", required = false) Boolean hasEndDate,
249+
Pageable pageable) {
250+
251+
try {
252+
Context context = obtainContext();
253+
254+
List<ResourcePolicy> policies;
255+
int total;
256+
257+
policies = resourcePolicyService.findByDate(context, hasStartDate, hasEndDate,
258+
Math.toIntExact(pageable.getOffset()),
259+
Math.toIntExact(pageable.getPageSize()));
260+
total = resourcePolicyService.countByDate(context, hasStartDate, hasEndDate);
261+
return converter.toRestPage(policies, pageable, total, utils.obtainProjection());
262+
} catch (SQLException e) {
263+
throw new RuntimeException("Database error while searching embargo policies: " + e.getMessage(), e);
264+
}
265+
}
266+
236267
@Override
237268
@PreAuthorize("isAuthenticated()")
238269
protected ResourcePolicyRest createAndReturn(Context context) throws AuthorizeException, SQLException {

dspace-server-webapp/src/test/java/org/dspace/app/rest/ResourcePolicyRestRepositoryIT.java

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import static com.jayway.jsonpath.JsonPath.read;
1111
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
12+
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
1213
import static org.hamcrest.Matchers.is;
1314
import static org.hamcrest.Matchers.nullValue;
1415
import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE;
@@ -4284,4 +4285,146 @@ public void updateResourcePolicyOfEPersonWithMultipleEPersonsTest() throws Excep
42844285
.andExpect(status().isUnprocessableEntity());
42854286
}
42864287

4288+
/**
4289+
* Setups test data for embargo policy tests including:
4290+
* - Community, Collection, and Item
4291+
* - ResourcePolicies with different date combinations
4292+
* - Predefined start and end dates for consistency
4293+
*
4294+
* @throws Exception if test data creation fails
4295+
*/
4296+
private void setupEmbargoTestData() throws Exception {
4297+
context.turnOffAuthorisationSystem();
4298+
4299+
try {
4300+
// Create test hierarchy
4301+
Community community = CommunityBuilder.createCommunity(context)
4302+
.withName("Test Community").build();
4303+
Collection collection = CollectionBuilder.createCollection(context, community)
4304+
.withName("Test Collection").build();
4305+
Item item = ItemBuilder.createItem(context, collection)
4306+
.withTitle("Item with Embargo").build();
4307+
4308+
// Create consistent embargo dates
4309+
Calendar calendar1 = Calendar.getInstance();
4310+
calendar1.set(Calendar.YEAR, 2019);
4311+
calendar1.set(Calendar.MONTH, 9);
4312+
calendar1.set(Calendar.DATE, 31);
4313+
Date embargoStartDate = calendar1.getTime();
4314+
4315+
Calendar calendar2 = Calendar.getInstance();
4316+
calendar2.set(Calendar.YEAR, 2200);
4317+
calendar2.set(Calendar.MONTH, 9);
4318+
calendar2.set(Calendar.DATE, 31);
4319+
Date embargoEndDate = calendar2.getTime();
4320+
4321+
// Create ResourcePolicies with different date combinations
4322+
ResourcePolicy rpWithStartDate = ResourcePolicyBuilder.createResourcePolicy(context, admin, null)
4323+
.withAction(Constants.READ)
4324+
.withDspaceObject(item)
4325+
.withStartDate(embargoStartDate)
4326+
.build();
4327+
4328+
ResourcePolicy rpWithEndDate = ResourcePolicyBuilder.createResourcePolicy(context, admin, null)
4329+
.withAction(Constants.READ)
4330+
.withDspaceObject(item)
4331+
.withEndDate(embargoEndDate)
4332+
.build();
4333+
4334+
ResourcePolicy rpWithEndDate2 = ResourcePolicyBuilder.createResourcePolicy(context, admin, null)
4335+
.withAction(Constants.READ)
4336+
.withDspaceObject(item)
4337+
.withEndDate(embargoEndDate)
4338+
.build();
4339+
4340+
ResourcePolicy rpWithBothDates = ResourcePolicyBuilder.createResourcePolicy(context, admin, null)
4341+
.withAction(Constants.READ)
4342+
.withDspaceObject(item)
4343+
.withStartDate(embargoStartDate)
4344+
.withEndDate(embargoEndDate)
4345+
.build();
4346+
4347+
ResourcePolicy rpWithoutDates = ResourcePolicyBuilder.createResourcePolicy(context, admin, null)
4348+
.withAction(Constants.READ)
4349+
.withDspaceObject(item)
4350+
.build();
4351+
} finally {
4352+
context.restoreAuthSystemState();
4353+
}
4354+
}
4355+
4356+
@Test
4357+
public void findEmbargoWithStartDate() throws Exception {
4358+
// Baseline count
4359+
int baselineCount = this.resourcePolicyService.countByDate(context, true, null);
4360+
4361+
setupEmbargoTestData();
4362+
4363+
String authToken = getAuthToken(admin.getEmail(), password);
4364+
4365+
getClient(authToken)
4366+
.perform(get("/api/authz/resourcepolicies/search/embargo?hasStartDate=true"))
4367+
.andExpect(jsonPath("$.page.totalElements", is(baselineCount + 2)));
4368+
// rpWithStartDate + rpWithBothDates
4369+
}
4370+
4371+
@Test
4372+
public void findEmbargoWithEndDate() throws Exception {
4373+
// Baseline count
4374+
int baselineCount = this.resourcePolicyService.countByDate(context, null, true);
4375+
4376+
setupEmbargoTestData();
4377+
4378+
String authToken = getAuthToken(admin.getEmail(), password);
4379+
4380+
getClient(authToken)
4381+
.perform(get("/api/authz/resourcepolicies/search/embargo?hasEndDate=true"))
4382+
.andExpect(jsonPath("$.page.totalElements", is(baselineCount + 3)));
4383+
// rpWithEndDate + rpWithEndDate2 + rpWithBothDates
4384+
}
4385+
4386+
@Test
4387+
public void findEmbargoWithoutDates() throws Exception {
4388+
// Baseline count
4389+
int baselineCount = this.resourcePolicyService.countByDate(context, false, false);
4390+
4391+
setupEmbargoTestData();
4392+
4393+
String authToken = getAuthToken(admin.getEmail(), password);
4394+
4395+
getClient(authToken)
4396+
.perform(get("/api/authz/resourcepolicies/search/embargo?hasStartDate=false&hasEndDate=false"))
4397+
.andExpect(jsonPath("$.page.totalElements", greaterThanOrEqualTo(baselineCount + 1)));
4398+
// rpWithoutDates
4399+
}
4400+
4401+
@Test
4402+
public void findEmbargoWithAnyDate() throws Exception {
4403+
// Baseline count
4404+
int baselineCount = this.resourcePolicyService.countByDate(context, null, null);
4405+
4406+
setupEmbargoTestData();
4407+
4408+
String authToken = getAuthToken(admin.getEmail(), password);
4409+
4410+
getClient(authToken)
4411+
.perform(get("/api/authz/resourcepolicies/search/embargo"))
4412+
.andExpect(jsonPath("$.page.totalElements", is(baselineCount + 4)));
4413+
// All our rps except rpWithoutDates
4414+
}
4415+
4416+
@Test
4417+
public void findEmbargoWithBothDates() throws Exception {
4418+
// Baseline count
4419+
int baselineCount = this.resourcePolicyService.countByDate(context, true, true);
4420+
4421+
setupEmbargoTestData();
4422+
4423+
String authToken = getAuthToken(admin.getEmail(), password);
4424+
4425+
getClient(authToken)
4426+
.perform(get("/api/authz/resourcepolicies/search/embargo?hasStartDate=true&hasEndDate=true"))
4427+
.andExpect(jsonPath("$.page.totalElements", is(baselineCount + 1)));
4428+
// rpWithBothDates
4429+
}
42874430
}

0 commit comments

Comments
 (0)