Skip to content

Commit 46a2151

Browse files
authored
Merge pull request #1746 from UNC-Libraries/access-surrogate-development
Access surrogate development
2 parents 49c0b96 + 5979d33 commit 46a2151

File tree

44 files changed

+1505
-53
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1505
-53
lines changed

indexing-solr/src/main/java/edu/unc/lib/boxc/indexing/solr/filter/SetContentStatusFilter.java

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
package edu.unc.lib.boxc.indexing.solr.filter;
22

3-
import java.util.ArrayList;
4-
import java.util.List;
5-
import java.util.Objects;
6-
7-
import edu.unc.lib.boxc.model.api.rdf.CdrView;
8-
import edu.unc.lib.boxc.operations.jms.viewSettings.ViewSettingRequest;
9-
import org.apache.jena.rdf.model.Resource;
10-
import org.slf4j.Logger;
11-
import org.slf4j.LoggerFactory;
12-
133
import edu.unc.lib.boxc.indexing.solr.exception.IndexingException;
144
import edu.unc.lib.boxc.indexing.solr.indexing.DocumentIndexingPackage;
5+
import edu.unc.lib.boxc.model.api.DatastreamType;
6+
import edu.unc.lib.boxc.model.api.ids.PID;
157
import edu.unc.lib.boxc.model.api.objects.ContentObject;
168
import edu.unc.lib.boxc.model.api.objects.FileObject;
179
import edu.unc.lib.boxc.model.api.objects.WorkObject;
1810
import edu.unc.lib.boxc.model.api.rdf.Cdr;
11+
import edu.unc.lib.boxc.model.api.rdf.CdrView;
12+
import edu.unc.lib.boxc.model.fcrepo.services.DerivativeService;
13+
import edu.unc.lib.boxc.operations.jms.viewSettings.ViewSettingRequest;
1914
import edu.unc.lib.boxc.search.api.FacetConstants;
15+
import org.apache.jena.rdf.model.Resource;
16+
import org.slf4j.Logger;
17+
import org.slf4j.LoggerFactory;
18+
19+
import java.nio.file.Files;
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
import java.util.Objects;
2023

2124
/**
2225
* Sets content-related status tags
@@ -25,6 +28,7 @@
2528
*
2629
*/
2730
public class SetContentStatusFilter implements IndexDocumentFilter{
31+
private DerivativeService derivativeService;
2832
private static final Logger log = LoggerFactory.getLogger(SetContentStatusFilter.class);
2933
@Override
3034
public void filter(DocumentIndexingPackage dip) throws IndexingException {
@@ -59,6 +63,11 @@ private List<String> determineContentStatus(DocumentIndexingPackage dip)
5963
if (parentResc.hasProperty(Cdr.useAsThumbnail, resc)) {
6064
status.add(FacetConstants.ASSIGNED_AS_THUMBNAIL);
6165
}
66+
if (hasAccessSurrogate(obj.getPid())) {
67+
status.add(FacetConstants.HAS_ACCESS_SURROGATE);
68+
} else {
69+
status.add(FacetConstants.NO_ACCESS_SURROGATE);
70+
}
6271
}
6372

6473
return status;
@@ -96,4 +105,13 @@ private void addWorkObjectStatuses(List<String> status, Resource resource) {
96105
status.add(FacetConstants.VIEW_BEHAVIOR_INDIVIDUALS);
97106
}
98107
}
108+
109+
private boolean hasAccessSurrogate(PID pid) {
110+
var accessSurrogatePath = derivativeService.getDerivativePath(pid, DatastreamType.ACCESS_SURROGATE);
111+
return Files.exists(accessSurrogatePath);
112+
}
113+
114+
public void setDerivativeService(DerivativeService derivativeService) {
115+
this.derivativeService = derivativeService;
116+
}
99117
}

indexing-solr/src/test/java/edu/unc/lib/boxc/indexing/solr/filter/SetContentStatusFilterTest.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@
33
import static org.junit.jupiter.api.Assertions.assertFalse;
44
import static org.junit.jupiter.api.Assertions.assertTrue;
55
import static org.mockito.ArgumentMatchers.any;
6+
import static org.mockito.ArgumentMatchers.eq;
67
import static org.mockito.Mockito.verify;
78
import static org.mockito.Mockito.when;
89
import static org.mockito.MockitoAnnotations.openMocks;
910

11+
import java.io.IOException;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
1014
import java.util.List;
1115

16+
import edu.unc.lib.boxc.model.api.DatastreamType;
17+
import edu.unc.lib.boxc.model.fcrepo.services.DerivativeService;
1218
import org.apache.jena.rdf.model.Property;
1319
import org.apache.jena.rdf.model.Resource;
1420
import org.junit.jupiter.api.AfterEach;
1521
import org.junit.jupiter.api.BeforeEach;
1622
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.api.io.TempDir;
1724
import org.mockito.ArgumentCaptor;
1825
import org.mockito.Captor;
1926
import org.mockito.Mock;
@@ -46,9 +53,13 @@ public class SetContentStatusFilterTest {
4653
private IndexDocumentBean idb;
4754
@Mock
4855
private Resource resc, fileResc;
56+
@Mock
57+
private DerivativeService derivativeService;
4958
@Captor
5059
private ArgumentCaptor<List<String>> listCaptor;
51-
60+
@TempDir
61+
public Path derivativeFolder;
62+
private Path accessSurrogatePath;
5263
private SetContentStatusFilter filter;
5364

5465
@BeforeEach
@@ -61,7 +72,11 @@ public void setUp() throws Exception {
6172
when(resc.hasProperty(any(Property.class))).thenReturn(false);
6273

6374
when(fileObj.getParent()).thenReturn(workObj);
75+
accessSurrogatePath = derivativeFolder.resolve("f277bb38-272c-471c-a28a-9887a1328a1f");
6476
filter = new SetContentStatusFilter();
77+
filter.setDerivativeService(derivativeService);
78+
when(derivativeService.getDerivativePath(any(), eq(DatastreamType.ACCESS_SURROGATE)))
79+
.thenReturn(accessSurrogatePath);
6580
}
6681

6782
@AfterEach
@@ -218,4 +233,44 @@ public void testIsAssignedThumbnail() throws Exception {
218233
verify(idb).setContentStatus(listCaptor.capture());
219234
assertTrue(listCaptor.getValue().contains(FacetConstants.ASSIGNED_AS_THUMBNAIL));
220235
}
236+
237+
@Test
238+
public void testFileObjectHasAccessSurrogate() throws IOException {
239+
Files.write(accessSurrogatePath, List.of("fake image"));
240+
when(workObj.getResource()).thenReturn(resc);
241+
when(dip.getContentObject()).thenReturn(fileObj);
242+
when(fileObj.getResource()).thenReturn(fileResc);
243+
244+
filter.filter(dip);
245+
246+
verify(idb).setContentStatus(listCaptor.capture());
247+
assertTrue(listCaptor.getValue().contains(FacetConstants.HAS_ACCESS_SURROGATE));
248+
}
249+
250+
@Test
251+
public void testFileObjectNoAccessSurrogate() {
252+
when(workObj.getResource()).thenReturn(resc);
253+
when(resc.hasProperty(Cdr.primaryObject, fileResc)).thenReturn(true);
254+
when(dip.getContentObject()).thenReturn(fileObj);
255+
when(fileObj.getResource()).thenReturn(fileResc);
256+
257+
filter.filter(dip);
258+
259+
verify(idb).setContentStatus(listCaptor.capture());
260+
assertTrue(listCaptor.getValue().contains(FacetConstants.NO_ACCESS_SURROGATE));
261+
}
262+
263+
@Test
264+
public void testWorkAccessSurrogate() throws IOException {
265+
Files.write(accessSurrogatePath, List.of("fake image"));
266+
when(workObj.getResource()).thenReturn(resc);
267+
when(dip.getContentObject()).thenReturn(workObj);
268+
when(workObj.getResource()).thenReturn(resc);
269+
270+
filter.filter(dip);
271+
272+
verify(idb).setContentStatus(listCaptor.capture());
273+
assertFalse(listCaptor.getValue().contains(FacetConstants.HAS_ACCESS_SURROGATE));
274+
assertFalse(listCaptor.getValue().contains(FacetConstants.NO_ACCESS_SURROGATE));
275+
}
221276
}

integration/src/test/resources/spring-test/solr-indexing-context.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
</bean>
172172

173173
<bean id="setContentStatusFilter" class="edu.unc.lib.boxc.indexing.solr.filter.SetContentStatusFilter">
174+
<property name="derivativeService" ref="derivativeService" />
174175
</bean>
175176

176177
<bean id="setContentTypeFilter" class="edu.unc.lib.boxc.indexing.solr.filter.SetContentTypeFilter">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package edu.unc.lib.boxc.operations.jms.accessSurrogates;
2+
3+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
4+
import edu.unc.lib.boxc.auth.api.models.AgentPrincipals;
5+
import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl;
6+
7+
import java.nio.file.Path;
8+
9+
/**
10+
* Request object for updating access surrogates of a FileObject
11+
* @author snluong
12+
*/
13+
public class AccessSurrogateRequest {
14+
public static String SET = "set";
15+
public static String DELETE = "delete";
16+
private String pidString;
17+
@JsonDeserialize(as = AgentPrincipalsImpl.class)
18+
private AgentPrincipals agent;
19+
private String action;
20+
private String mimetype;
21+
private Path filePath;
22+
23+
public String getPidString() {
24+
return pidString;
25+
}
26+
27+
public void setPidString(String pidString) {
28+
this.pidString = pidString;
29+
}
30+
31+
public AgentPrincipals getAgent() {
32+
return agent;
33+
}
34+
35+
public void setAgent(AgentPrincipals agent) {
36+
this.agent = agent;
37+
}
38+
39+
public String getAction() {
40+
return action;
41+
}
42+
43+
public void setAction(String action) {
44+
this.action = action;
45+
}
46+
47+
public Path getFilePath() {
48+
return filePath;
49+
}
50+
51+
public void setFilePath(Path filePath) {
52+
this.filePath = filePath;
53+
}
54+
55+
public String getMimetype() {
56+
return mimetype;
57+
}
58+
59+
public void setMimetype(String mimetype) {
60+
this.mimetype = mimetype;
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package edu.unc.lib.boxc.operations.jms.accessSurrogates;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.fasterxml.jackson.databind.ObjectWriter;
5+
import edu.unc.lib.boxc.operations.jms.MessageSender;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import java.io.IOException;
10+
11+
/**
12+
* Service for sending requests to update access surrogates of a FileObject
13+
*/
14+
public class AccessSurrogateRequestSender extends MessageSender {
15+
private static final Logger log = LoggerFactory.getLogger(AccessSurrogateRequestSender.class);
16+
private static final ObjectWriter MAPPER = new ObjectMapper().writerFor(AccessSurrogateRequest.class);
17+
18+
public void sendToQueue(AccessSurrogateRequest request) throws IOException {
19+
String messageBody = MAPPER.writeValueAsString(request);
20+
sendMessage(messageBody);
21+
log.info("Job to {} access surrogates has been queued for file {} by {}",
22+
request.getAction(), request.getPidString(), request.getAgent().getUsername());
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package edu.unc.lib.boxc.operations.jms.accessSurrogates;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.fasterxml.jackson.databind.ObjectReader;
6+
import com.fasterxml.jackson.databind.ObjectWriter;
7+
import edu.unc.lib.boxc.operations.jms.accessSurrogates.AccessSurrogateRequest;
8+
9+
import java.io.IOException;
10+
11+
/**
12+
* Helper methods for serializing and deserializing access surrogate requests
13+
* @author snluong
14+
*/
15+
public class AccessSurrogateRequestSerializationHelper {
16+
private static final ObjectWriter REQUEST_WRITER;
17+
private static final ObjectReader REQUEST_READER;
18+
19+
static {
20+
ObjectMapper mapper = new ObjectMapper();
21+
REQUEST_WRITER = mapper.writerFor(AccessSurrogateRequest.class);
22+
REQUEST_READER = mapper.readerFor(AccessSurrogateRequest.class);
23+
}
24+
25+
private AccessSurrogateRequestSerializationHelper() {
26+
}
27+
28+
public static String toJson(AccessSurrogateRequest request) throws JsonProcessingException {
29+
return REQUEST_WRITER.writeValueAsString(request);
30+
}
31+
32+
public static AccessSurrogateRequest toRequest(String json) throws IOException {
33+
return REQUEST_READER.readValue(json);
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package edu.unc.lib.boxc.operations.jms.accessSurrogates;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import edu.unc.lib.boxc.auth.api.models.AgentPrincipals;
5+
import edu.unc.lib.boxc.auth.fcrepo.models.AccessGroupSetImpl;
6+
import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl;
7+
import edu.unc.lib.boxc.model.api.ids.PID;
8+
import edu.unc.lib.boxc.model.fcrepo.ids.PIDs;
9+
import org.junit.jupiter.api.Test;
10+
import org.mockito.Mock;
11+
12+
import java.io.IOException;
13+
import java.nio.file.Path;
14+
import java.util.UUID;
15+
16+
import static edu.unc.lib.boxc.operations.jms.accessSurrogates.AccessSurrogateRequest.DELETE;
17+
import static org.junit.jupiter.api.Assertions.assertEquals;
18+
19+
public class AccessSurrogateRequestSerializationHelperTest {
20+
private final AgentPrincipals agent = new AgentPrincipalsImpl("user", new AccessGroupSetImpl("agroup"));
21+
private final PID pid = PIDs.get(UUID.randomUUID().toString());
22+
@Mock
23+
private Path path;
24+
25+
@Test
26+
public void testHelperSuccess() throws IOException {
27+
var request = new AccessSurrogateRequest();
28+
request.setPidString(pid.getId());
29+
request.setFilePath(path);
30+
request.setAgent(agent);
31+
request.setAction(DELETE);
32+
request.setMimetype("image/jpeg");
33+
34+
var json = AccessSurrogateRequestSerializationHelper.toJson(request);
35+
var helperRequest = AccessSurrogateRequestSerializationHelper.toRequest(json);
36+
37+
assertEquals(request.getAction(), helperRequest.getAction());
38+
assertEquals(request.getAgent().getPrincipals(), helperRequest.getAgent().getPrincipals());
39+
assertEquals(request.getFilePath(), helperRequest.getFilePath());
40+
assertEquals(request.getMimetype(), helperRequest.getMimetype());
41+
assertEquals(request.getPidString(), helperRequest.getPidString());
42+
}
43+
}

web-services-app/src/main/java/edu/unc/lib/boxc/web/services/utils/ImageServerUtil.java renamed to operations/src/main/java/edu/unc/lib/boxc/operations/api/images/ImageServerUtil.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package edu.unc.lib.boxc.web.services.utils;
1+
package edu.unc.lib.boxc.operations.api.images;
22

33
import java.net.URLEncoder;
44
import java.nio.charset.StandardCharsets;
@@ -15,15 +15,22 @@ public class ImageServerUtil {
1515
private ImageServerUtil() {
1616
}
1717

18+
/**
19+
* Returns an unencoded image service ID with .jp2 extension
20+
* @param id
21+
* @return
22+
*/
23+
public static String getImageServiceId(String id) {
24+
return idToPath(id, 4, 2) + id + ".jp2";
25+
}
26+
1827
/**
1928
* Returns the object ID in proper encoded format with .jp2 extension
2029
* @param id
2130
* @return
2231
*/
2332
public static String getImageServerEncodedId(String id) {
24-
var idPathEncoded = URLEncoder.encode(idToPath(id, 4, 2), StandardCharsets.UTF_8);
25-
var idEncoded = URLEncoder.encode(id, StandardCharsets.UTF_8);
26-
return idPathEncoded + idEncoded + ".jp2";
33+
return URLEncoder.encode(getImageServiceId(id));
2734
}
2835

2936
/**

search-api/src/main/java/edu/unc/lib/boxc/search/api/FacetConstants.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ public abstract class FacetConstants {
2929
public static final String VIEW_BEHAVIOR_INDIVIDUALS = "View Behavior Individuals";
3030
public static final String VIEW_BEHAVIOR_PAGED = "View Behavior Paged";
3131
public static final String VIEW_BEHAVIOR_CONTINUOUS = "View Behavior Continuous";
32-
32+
public static final String HAS_ACCESS_SURROGATE = "Has Access Surrogate";
33+
public static final String NO_ACCESS_SURROGATE = "No Access Surrogate";
3334
}

services-camel-app/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@
246246
<artifactId>junit-vintage-engine</artifactId>
247247
<version>${junit.jupiter.version}</version>
248248
</dependency>
249+
<dependency>
250+
<groupId>com.github.tomakehurst</groupId>
251+
<artifactId>wiremock-jre8</artifactId>
252+
</dependency>
249253

250254
<dependency>
251255
<groupId>edu.unc.lib.cdr</groupId>

0 commit comments

Comments
 (0)