Skip to content

Commit b15ba65

Browse files
committed
Merge pull request #434 from UNC-Libraries/related-items
Full record page navigation
2 parents 0d3f6db + 17ee7fb commit b15ba65

File tree

7 files changed

+75
-449
lines changed

7 files changed

+75
-449
lines changed

Diff for: access-common/src/main/java/edu/unc/lib/dl/ui/service/SolrQueryLayerService.java

+61-149
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public class SolrQueryLayerService extends SolrSearchService {
7777
protected SearchStateFactory searchStateFactory;
7878
protected PID collectionsPid;
7979
protected ObjectPathFactory pathFactory;
80+
81+
private static int NEIGHBOR_SEEK_PAGE_SIZE = 500;
8082

8183
/**
8284
* Returns a list of the most recently added items in the collection
@@ -286,10 +288,9 @@ public List<BriefObjectMetadataBean> getParentCollectionValues(FacetFieldObject
286288
}
287289

288290
/**
289-
* Retrieves a list of the nearest windowSize neighbors within the nearest parent collection or folder around the
290-
* item metadata, based on the order field of the item. The first windowSize - 1 neighbors are retrieved to each side
291-
* of the item, and trimmed so that there are always windowSize - 1 neighbors surrounding the item if possible. If no
292-
* order field is available, a list of arbitrary windowSize neighbors is returned.
291+
* Retrieves a list of the closest windowSize neighbors within the parent container of the specified object,
292+
* using the default sort order. The first windowSize / 2 - 1 neighbors are retrieved to each side
293+
* of the item, and trimmed so that there are always windowSize - 1 neighbors surrounding the item if possible.
293294
*
294295
* @param metadata
295296
* Record which the window pivots around.
@@ -303,187 +304,98 @@ public List<BriefObjectMetadataBean> getNeighboringItems(BriefObjectMetadataBean
303304
AccessGroupSet accessGroups) {
304305

305306
// Get the common access restriction clause (starts with "AND ...")
306-
307307
StringBuilder accessRestrictionClause = new StringBuilder();
308308

309309
try {
310310
addAccessRestrictions(accessRestrictionClause, accessGroups);
311311
} catch (AccessRestrictionException e) {
312312
// If the user doesn't have any access groups, they don't have access to anything, return null.
313-
LOG.error(e.getMessage());
313+
LOG.error("Attempted to get neighboring items without creditentials", e);
314314
return null;
315315
}
316316

317-
// Prepare the common query object, including a filter for resource type and the
318-
// facet which selects only the item's siblings.
319-
317+
// Restrict query to files/aggregates and objects within the same parent
320318
SolrQuery solrQuery = new SolrQuery();
319+
solrQuery.setQuery("*:*" + accessRestrictionClause);
321320

322321
solrQuery.setFacet(true);
323322
solrQuery.addFilterQuery(solrSettings.getFieldName(SearchFieldKeys.RESOURCE_TYPE.name()) + ":File "
324323
+ solrSettings.getFieldName(SearchFieldKeys.RESOURCE_TYPE.name()) + ":Aggregate");
325324

326325
CutoffFacet ancestorPath = null;
327-
328326
if (metadata.getResourceType().equals(searchSettings.resourceTypeFile)
329327
|| metadata.getResourceType().equals(searchSettings.resourceTypeAggregate)) {
330328
ancestorPath = metadata.getAncestorPathFacet();
331329
} else {
332330
ancestorPath = metadata.getPath();
333331
}
334-
335332
if (ancestorPath != null) {
336333
// We want only objects at the same level of the hierarchy
337334
ancestorPath.setCutoff(ancestorPath.getHighestTier() + 1);
338335

339336
facetFieldUtil.addToSolrQuery(ancestorPath, solrQuery);
340337
}
341-
342-
// If this item has no display order, get arbitrary items surrounding it.
343-
344-
Long pivotOrder = metadata.getDisplayOrder();
345-
346-
if (pivotOrder == null) {
347-
348-
LOG.debug("No display order, just querying for " + windowSize + " siblings");
349-
350-
StringBuilder query = new StringBuilder();
351-
352-
List<BriefObjectMetadataBean> list = null;
353-
354-
query.append("*:*");
355-
query.append(accessRestrictionClause);
356-
solrQuery.setQuery(query.toString());
357-
358-
solrQuery.setStart(0);
359-
solrQuery.setRows(windowSize);
360-
361-
solrQuery.setSort(solrSettings.getFieldName(SearchFieldKeys.DISPLAY_ORDER.name()), SolrQuery.ORDER.desc);
362-
363-
try {
364-
QueryResponse queryResponse = this.executeQuery(solrQuery);
365-
list = queryResponse.getBeans(BriefObjectMetadataBean.class);
366-
} catch (SolrServerException e) {
367-
LOG.error("Error retrieving Neighboring items: " + e);
368-
return null;
369-
}
370-
371-
return list;
372-
373-
// Otherwise, query for items surrounding this item.
374-
375-
} else {
376-
377-
LOG.debug("Display order is " + pivotOrder);
378-
379-
// Find the right and left lists
380-
381-
StringBuilder query;
382-
383-
List<BriefObjectMetadataBean> leftList = null;
384-
List<BriefObjectMetadataBean> rightList = null;
385-
386-
solrQuery.setStart(0);
387-
solrQuery.setRows(windowSize - 1);
388-
389-
// Right list
390-
391-
query = new StringBuilder();
392-
393-
query.append(solrSettings.getFieldName(SearchFieldKeys.DISPLAY_ORDER.name())).append(":[")
394-
.append(pivotOrder + 1).append(" TO *]");
395-
query.append(accessRestrictionClause);
396-
solrQuery.setQuery(query.toString());
397-
398-
solrQuery.setSort(solrSettings.getFieldName(SearchFieldKeys.DISPLAY_ORDER.name()), SolrQuery.ORDER.asc);
399-
400-
try {
401-
QueryResponse queryResponse = this.executeQuery(solrQuery);
402-
rightList = queryResponse.getBeans(BriefObjectMetadataBean.class);
403-
} catch (SolrServerException e) {
404-
LOG.error("Error retrieving Neighboring items: " + e);
405-
return null;
406-
}
407-
408-
LOG.debug("Got " + rightList.size() + " items for right list");
409-
410-
// Left list
411-
412-
// (Note that display order stuff is reversed.)
413-
414-
query = new StringBuilder();
415-
416-
query.append(solrSettings.getFieldName(SearchFieldKeys.DISPLAY_ORDER.name())).append(":[* TO ")
417-
.append(pivotOrder - 1).append("]");
418-
query.append(accessRestrictionClause);
419-
solrQuery.setQuery(query.toString());
420-
421-
solrQuery.setSort(solrSettings.getFieldName(SearchFieldKeys.DISPLAY_ORDER.name()), SolrQuery.ORDER.desc);
422-
338+
339+
// Sort neighbors using the default sort
340+
addSort(solrQuery, "default", true);
341+
342+
343+
// Query for ids in this container in groups of NEIGHBOR_SEEK_PAGE_SIZE until we find the offset of the object
344+
solrQuery.setRows(NEIGHBOR_SEEK_PAGE_SIZE);
345+
solrQuery.setFields("id");
346+
347+
long total = -1;
348+
int start = 0;
349+
pageLoop: do {
423350
try {
351+
solrQuery.setStart(start);
424352
QueryResponse queryResponse = this.executeQuery(solrQuery);
425-
leftList = queryResponse.getBeans(BriefObjectMetadataBean.class);
353+
total = queryResponse.getResults().getNumFound();
354+
for (SolrDocument doc : queryResponse.getResults()) {
355+
if (metadata.getId().equals(doc.getFieldValue("id"))) {
356+
break pageLoop;
357+
}
358+
start++;
359+
}
426360
} catch (SolrServerException e) {
427361
LOG.error("Error retrieving Neighboring items: " + e);
428362
return null;
429363
}
430-
431-
LOG.debug("Got " + leftList.size() + " items for left list");
432-
433-
// Trim the lists
434-
435-
int halfWindow = windowSize / 2;
436-
437-
// If we have enough in both lists, trim both to be
438-
// halfWindow long.
439-
440-
if (leftList.size() >= halfWindow && rightList.size() >= halfWindow) {
441-
442-
LOG.debug("Trimming both lists");
443-
444-
leftList.subList(halfWindow, leftList.size()).clear();
445-
rightList.subList(halfWindow, rightList.size()).clear();
446-
447-
// If we don't have enough in the left list and we have extra in the right list,
448-
// try to pick up the slack by trimming fewer items from the right list.
449-
450-
} else if (leftList.size() < halfWindow && rightList.size() > halfWindow) {
451-
452-
LOG.debug("Picking up slack from right list");
453-
454-
// How much extra do we need from the right list?
455-
456-
int extra = halfWindow - leftList.size();
457-
458-
// Only "take" the extra (ie, clear less of the right list) if we have it available.
459-
460-
if (halfWindow + extra < rightList.size())
461-
rightList.subList(halfWindow + extra, rightList.size()).clear();
462-
463-
} else if (rightList.size() < halfWindow && leftList.size() > halfWindow) {
464-
465-
LOG.debug("Picking up slack from left list");
466-
467-
int extra = halfWindow - rightList.size();
468-
469-
if (halfWindow + extra < leftList.size())
470-
leftList.subList(halfWindow + extra, leftList.size()).clear();
471-
364+
} while (start < total);
365+
366+
// Wasn't found, no neighbors shall be forthcoming
367+
if (start >= total) {
368+
return null;
369+
}
370+
371+
// Calculate the starting index for the window, so that object is as close to the middle as possible
372+
long left = start - (windowSize / 2);
373+
long right = start + (windowSize / 2);
374+
375+
if (left < 0) {
376+
right -= left;
377+
left = 0;
378+
}
379+
380+
if (right >= total) {
381+
left -= (right - total) + 1;
382+
if (left < 0) {
383+
left = 0;
472384
}
473-
474-
// (Otherwise, we do no trimming, since both lists are smaller or the same size
475-
// as the window.)
476-
477-
// Assemble the result.
478-
479-
Collections.reverse(leftList);
480-
leftList.add(metadata);
481-
leftList.addAll(rightList);
482-
483-
return leftList;
484-
485385
}
486-
386+
387+
// Query for the windowSize of objects
388+
solrQuery.setFields(new String[0]);
389+
solrQuery.setRows(windowSize);
390+
solrQuery.setStart((int) left);
391+
392+
try {
393+
QueryResponse queryResponse = this.executeQuery(solrQuery);
394+
return queryResponse.getBeans(BriefObjectMetadataBean.class);
395+
} catch (SolrServerException e) {
396+
LOG.error("Error retrieving Neighboring items: " + e);
397+
return null;
398+
}
487399
}
488400

489401
/**

Diff for: access/src/main/java/edu/unc/lib/dl/ui/controller/FullRecordController.java

-13
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
import edu.unc.lib.dl.search.solr.util.SearchFieldKeys;
5959
import edu.unc.lib.dl.ui.exception.InvalidRecordRequestException;
6060
import edu.unc.lib.dl.ui.exception.RenderViewException;
61-
import edu.unc.lib.dl.ui.model.RecordNavigationState;
6261
import edu.unc.lib.dl.ui.util.AccessUtil;
6362
import edu.unc.lib.dl.ui.view.XSLViewResolver;
6463
import edu.unc.lib.dl.util.ContentModelHelper;
@@ -214,18 +213,6 @@ public String getFullRecord(String pid, Model model, HttpServletRequest request)
214213
applyContainerSettings(pid, foxmlView, model, fullObjectView != null);
215214
}
216215

217-
// Store search state information to the users session to enable page to page navigation
218-
RecordNavigationState recordNavigationState = (RecordNavigationState) request.getSession().getAttribute(
219-
"recordNavigationState");
220-
if (recordNavigationState != null) {
221-
int index = recordNavigationState.indexOf(pid);
222-
if (index > -1) {
223-
recordNavigationState.setCurrentRecordId(pid);
224-
recordNavigationState.setCurrentRecordIndex(index);
225-
request.getSession().setAttribute("recordNavigationState", recordNavigationState);
226-
}
227-
}
228-
229216
model.addAttribute("listAccess", listAccess);
230217

231218
model.addAttribute("pageSubtitle", briefObject.getTitle());

Diff for: access/src/main/java/edu/unc/lib/dl/ui/controller/FullRecordNavigationController.java

-105
This file was deleted.

0 commit comments

Comments
 (0)