Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paged display development #1698

Merged
merged 19 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public enum Permission {
changePatronAccess,
assignStaffRoles,
editResourceType,
editViewSettings,
runEnhancements,
reindex;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static edu.unc.lib.boxc.auth.api.Permission.destroy;
import static edu.unc.lib.boxc.auth.api.Permission.editDescription;
import static edu.unc.lib.boxc.auth.api.Permission.editResourceType;
import static edu.unc.lib.boxc.auth.api.Permission.editViewSettings;
import static edu.unc.lib.boxc.auth.api.Permission.ingest;
import static edu.unc.lib.boxc.auth.api.Permission.markForDeletion;
import static edu.unc.lib.boxc.auth.api.Permission.markForDeletionUnit;
Expand Down Expand Up @@ -53,7 +54,8 @@ public enum UserRole {
// Staff roles
canAccess("canAccess", true, canViewOriginals, viewHidden),
canIngest("canIngest", true, canAccess, ingest),
canDescribe("canDescribe", true, canAccess, editDescription, bulkUpdateDescription),
canDescribe("canDescribe", true, canAccess,
editDescription, bulkUpdateDescription, editViewSettings),
canProcess("canProcess", true, canDescribe,
move, orderMembers, markForDeletion, changePatronAccess),
canManage("canManage", true, canProcess,
Expand Down
2 changes: 2 additions & 0 deletions etc/solr-config/access/conf/schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@
<field name="timestamp" type="date" indexed="true" stored="true" default="NOW" multiValued="false"/>
<!-- Descriptive Fields -->
<field name="title" type="sortableText" indexed="true" stored="true" required="true"/>
<!-- View behavior for UV -->
<field name="viewBehavior" type="string" indexed="true" stored="true" />

<!-- Index fields -->
<!-- Specific field indexes -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import edu.unc.lib.boxc.model.api.rdf.CdrView;
import edu.unc.lib.boxc.operations.jms.viewSettings.ViewSettingRequest;
import org.apache.jena.rdf.model.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -79,5 +82,18 @@ private void addWorkObjectStatuses(List<String> status, Resource resource) {
} else {
status.add(FacetConstants.NO_THUMBNAIL_ASSIGNED);
}

if (resource.hasProperty(CdrView.viewBehavior)) {
var viewBehavior = resource.getProperty(CdrView.viewBehavior).getString();
if (Objects.equals(viewBehavior, ViewSettingRequest.ViewBehavior.PAGED.getString())) {
status.add(FacetConstants.VIEW_BEHAVIOR_PAGED);
} else if (Objects.equals(viewBehavior, ViewSettingRequest.ViewBehavior.CONTINUOUS.getString())) {
status.add(FacetConstants.VIEW_BEHAVIOR_CONTINUOUS);
} else {
status.add(FacetConstants.VIEW_BEHAVIOR_INDIVIDUALS);
}
} else {
status.add(FacetConstants.VIEW_BEHAVIOR_INDIVIDUALS);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package edu.unc.lib.boxc.indexing.solr.filter;

import edu.unc.lib.boxc.indexing.solr.exception.IndexingException;
import edu.unc.lib.boxc.indexing.solr.indexing.DocumentIndexingPackage;
import edu.unc.lib.boxc.model.api.rdf.CdrView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Filter which sets a work's view behavior. Updates the viewBehavior field.
*
* @author snluong
*/
public class SetViewBehaviorFilter implements IndexDocumentFilter {
private static final Logger log = LoggerFactory.getLogger(SetViewBehaviorFilter.class);

@Override
public void filter(DocumentIndexingPackage dip) throws IndexingException {
log.debug("Performing SetViewBehavior for object {}", dip.getPid());
var resource = dip.getContentObject().getResource();
var doc = dip.getDocument();
var behavior = resource.hasProperty(CdrView.viewBehavior) ?
resource.getProperty(CdrView.viewBehavior).getString() : null ;

doc.setViewBehavior(behavior);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package edu.unc.lib.boxc.indexing.solr.filter;

import edu.unc.lib.boxc.indexing.solr.indexing.DocumentIndexingPackage;
import edu.unc.lib.boxc.indexing.solr.indexing.DocumentIndexingPackageDataLoader;
import edu.unc.lib.boxc.model.api.ids.PID;
import edu.unc.lib.boxc.model.api.objects.WorkObject;
import edu.unc.lib.boxc.model.api.rdf.CdrView;
import edu.unc.lib.boxc.model.fcrepo.ids.PIDs;
import edu.unc.lib.boxc.operations.jms.viewSettings.ViewSettingRequest;
import edu.unc.lib.boxc.search.solr.models.IndexDocumentBean;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Statement;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.openMocks;

public class SetViewBehaviorFilterTest {
private static final String WORK_UUID = "f277bb38-272c-471c-a28a-9887a1328a1f";
private AutoCloseable closeable;
@Mock
private DocumentIndexingPackageDataLoader documentIndexingPackageDataLoader;
@Mock
private Resource resource;
@Mock
private Statement stmt;
private SetViewBehaviorFilter filter;
private DocumentIndexingPackage dip;
private IndexDocumentBean idb;
private PID workPid;

@BeforeEach
public void setup() {
closeable = openMocks(this);
workPid = PIDs.get(WORK_UUID);
dip = new DocumentIndexingPackage(workPid, null, documentIndexingPackageDataLoader);
dip.setPid(workPid);
idb = dip.getDocument();
filter = new SetViewBehaviorFilter();
}

@AfterEach
void closeService() throws Exception {
closeable.close();
}

@Test
public void testWithWorkObject() {
var work = mock(WorkObject.class);
var behavior = ViewSettingRequest.ViewBehavior.PAGED.getString();
when(documentIndexingPackageDataLoader.getContentObject(dip)).thenReturn(work);
when(work.getResource()).thenReturn(resource);
when(resource.hasProperty(eq(CdrView.viewBehavior))).thenReturn(true);
when(resource.getProperty(eq(CdrView.viewBehavior))).thenReturn(stmt);
when(stmt.getString()).thenReturn(behavior);

filter.filter(dip);

assertEquals(behavior, idb.getViewBehavior());
}

@Test
public void testWithWorkObjectWithoutViewBehavior() {
var work = mock(WorkObject.class);
when(documentIndexingPackageDataLoader.getContentObject(dip)).thenReturn(work);
when(work.getResource()).thenReturn(resource);
when(resource.hasProperty(eq(CdrView.viewBehavior))).thenReturn(false);

filter.filter(dip);

assertNull(idb.getViewBehavior());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package edu.unc.lib.boxc.model.api.rdf;

import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.Resource;

import static org.apache.jena.rdf.model.ResourceFactory.createProperty;
import static org.apache.jena.rdf.model.ResourceFactory.createResource;

/**
* @author snluong
*/
public class CdrView {
private CdrView() {
}

/** The namespace of the vocabulary as a string */
public static final String NS = "http://cdr.unc.edu/definitions/view#";

/** The namespace of the vocabulary as a string
* @see #NS */
public static String getURI() {
return NS; }

/** The namespace of the vocabulary as a resource */
public static final Resource NAMESPACE = createResource( NS );

/** Used to define the IIIFv3 view "behavior" property for works.
* Valid values: https://iiif.io/api/presentation/3.0/#behavior */
public static final Property viewBehavior = createProperty(
"http://cdr.unc.edu/definitions/view#behavior");
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public enum IndexingActionType {
UPDATE_MEMBER_ORDER("Update Member Order", "Update the order of members within an object"),
UPDATE_MEMBER_ORDER_CHILD("Update Member Order Child", "Update the order of a container member"),
UPDATE_MEMBER_ORDER_PARENT("Update Member Order Parent", "Update a container after its order changed"),
UPDATE_VIEW_BEHAVIOR("Update View Behavior", "Update the view behavior for a work"),
UNKNOWN("Unknown action", "Unknown action");

private final String label;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package edu.unc.lib.boxc.operations.jms.viewSettings;


import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import edu.unc.lib.boxc.auth.api.models.AgentPrincipals;
import edu.unc.lib.boxc.auth.fcrepo.models.AgentPrincipalsImpl;

/**
* Request object for updating the view settings of the UV
* @author sharonluong
*/
public class ViewSettingRequest {
private String objectPidString;
private ViewBehavior viewBehavior;

@JsonDeserialize(as = AgentPrincipalsImpl.class)
private AgentPrincipals agent;
public enum ViewBehavior {
INDIVIDUALS,
PAGED,
CONTINUOUS;

public String getString() {
return this.name().toLowerCase();
}

public static ViewBehavior caseInsensitiveValueOf(String behavior) {
return valueOf(behavior.toUpperCase());
}
}

public String getObjectPidString() {
return objectPidString;
}

public void setObjectPidString(String objectPidString) {
this.objectPidString = objectPidString;
}

public ViewBehavior getViewBehavior() {
return viewBehavior;
}

public void setViewBehavior(ViewBehavior viewBehavior) {
this.viewBehavior = viewBehavior;
}

public AgentPrincipals getAgent() {
return agent;
}

public void setAgent(AgentPrincipals agent) {
this.agent = agent;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package edu.unc.lib.boxc.operations.jms.viewSettings;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import edu.unc.lib.boxc.operations.jms.MessageSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
* Service for sending requests to update view settings of a work object
*/
public class ViewSettingRequestSender extends MessageSender {
private static final Logger log = LoggerFactory.getLogger(ViewSettingRequestSender.class);
private static final ObjectWriter MAPPER = new ObjectMapper().writerFor(ViewSettingRequest.class);

public void sendToQueue(ViewSettingRequest request) throws IOException {
String messageBody = MAPPER.writeValueAsString(request);
sendMessage(messageBody);
log.info("Job to update view setting has been queued for work {} by {}",
request.getObjectPidString(), request.getAgent().getUsername());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package edu.unc.lib.boxc.operations.jms.viewSettings;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;

import java.io.IOException;

/**
* Helper methods for serializing and deserializing view setting requests
* @author snluong
*/
public class ViewSettingRequestSerializationHelper {
private static final ObjectWriter REQUEST_WRITER;
private static final ObjectReader REQUEST_READER;

static {
ObjectMapper mapper = new ObjectMapper();
REQUEST_WRITER = mapper.writerFor(ViewSettingRequest.class);
REQUEST_READER = mapper.readerFor(ViewSettingRequest.class);
}

private ViewSettingRequestSerializationHelper() {
}

public static String toJson(ViewSettingRequest request) throws JsonProcessingException {
return REQUEST_WRITER.writeValueAsString(request);
}

public static ViewSettingRequest toRequest(String json) throws IOException {
return REQUEST_READER.readValue(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@ public abstract class FacetConstants {
public static final String HAS_THUMBNAIL_ASSIGNED = "Has Assigned Thumbnail";
public static final String NO_THUMBNAIL_ASSIGNED = "No Assigned Thumbnail";
public static final String ASSIGNED_AS_THUMBNAIL = "Assigned As Thumbnail";
public static final String VIEW_BEHAVIOR_INDIVIDUALS = "View Behavior Individuals";
public static final String VIEW_BEHAVIOR_PAGED = "View Behavior Paged";
public static final String VIEW_BEHAVIOR_CONTINUOUS = "View Behavior Continuous";

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ public enum SearchFieldKey {
TIMESTAMP("timestamp", "timestamp", "Timestamp"),
TITLE("title", "title", "Title"),
TITLE_INDEX("titleIndex", "titleIndex", "Title Index"),
VERSION("_version_", "version", "Version");
VERSION("_version_", "version", "Version"),
VIEW_BEHAVIOR("viewBehavior", "viewBehavior", "View Behavior");

private final String solrField;
private final String displayLabel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,6 @@ public interface ContentObjectRecord {
String getThumbnailId();

void setThumbnailId(String id);

String getViewBehavior();
}
Original file line number Diff line number Diff line change
Expand Up @@ -371,4 +371,9 @@ public String getThumbnailId() {
public void setThumbnailId(String id) {
representative.setThumbnailId(id);
}

@Override
public String getViewBehavior() {
return representative.getViewBehavior();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,14 @@ public void setMemberOrderId(Integer value) {
fields.put(SearchFieldKey.MEMBER_ORDER_ID.getSolrField(), value);
}

public String getViewBehavior() {
return (String) fields.get(SearchFieldKey.VIEW_BEHAVIOR.getSolrField());
}
@Field
public void setViewBehavior(String behavior) {
fields.put(SearchFieldKey.VIEW_BEHAVIOR.getSolrField(), behavior);
}

public String getTitle() {
return (String) fields.get(TITLE.getSolrField());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public abstract class AbstractQueryService {
SearchFieldKey.SUBJECT.name(),
SearchFieldKey.TIMESTAMP.name(),
SearchFieldKey.TITLE.name(),
SearchFieldKey.VERSION.name());
SearchFieldKey.VERSION.name(),
SearchFieldKey.VIEW_BEHAVIOR.name());

@Autowired
protected SearchSettings searchSettings;
Expand Down
Loading
Loading