mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Merge pull request #8047 from mspalti/dynamic-default-dims
Dynamic IIIF canvas dimensions
This commit is contained in:
@@ -34,15 +34,6 @@ public class IIIFApiQueryServiceImpl implements IIIFApiQueryService {
|
||||
|
||||
@Override
|
||||
public int[] getImageDimensions(Bitstream bitstream) {
|
||||
return getIiifImageDimensions(bitstream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves image dimensions from the image server (IIIF Image API v.2.1.1).
|
||||
* @param bitstream the bitstream DSO
|
||||
* @return image dimensions
|
||||
*/
|
||||
private int[] getIiifImageDimensions(Bitstream bitstream) {
|
||||
int[] arr = new int[2];
|
||||
String path = IIIFSharedUtils.getInfoJsonPath(bitstream);
|
||||
URL url;
|
||||
|
@@ -13,14 +13,15 @@ import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Exposes the Spring web application's IIIF cache evict service to the DSpace event consumer.
|
||||
* Exposes the Spring application's IIIF cache evict service to the DSpace event consumer.
|
||||
*/
|
||||
@Component
|
||||
public class CacheEvictBeanLocator implements ApplicationContextAware {
|
||||
|
||||
private static ApplicationContext context;
|
||||
|
||||
private static final String CACHE_SERVICE = "cacheEvictService";
|
||||
private static final String MANIFESTS_CACHE_EVICT_SERVICE = "manifestsCacheEvictService";
|
||||
private static final String CANVAS_DIMENSIONS_EVICT_SERVICE = "canvasCacheEvictService";
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext appContext)
|
||||
@@ -32,9 +33,16 @@ public class CacheEvictBeanLocator implements ApplicationContextAware {
|
||||
return context;
|
||||
}
|
||||
|
||||
public static CacheEvictService getCacheEvictService() {
|
||||
public static ManifestsCacheEvictService getManifestsCacheEvictService() {
|
||||
if (context != null) {
|
||||
return (CacheEvictService) context.getBean(CACHE_SERVICE);
|
||||
return (ManifestsCacheEvictService) context.getBean(MANIFESTS_CACHE_EVICT_SERVICE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CanvasCacheEvictService getCanvasCacheEvictService() {
|
||||
if (context != null) {
|
||||
return (CanvasCacheEvictService) context.getBean(CANVAS_DIMENSIONS_EVICT_SERVICE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.iiif.consumer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CanvasCacheEvictService {
|
||||
|
||||
// The cache that is managed by this service.
|
||||
static final String CACHE_NAME = "canvasdimensions";
|
||||
|
||||
@Autowired
|
||||
CacheManager cacheManager;
|
||||
|
||||
public void evictSingleCacheValue(String cacheKey) {
|
||||
Objects.requireNonNull(cacheManager.getCache(CACHE_NAME)).evict(cacheKey);
|
||||
}
|
||||
|
||||
}
|
@@ -34,6 +34,9 @@ public class IIIFCacheEventConsumer implements Consumer {
|
||||
// Collects modified items for individual removal from cache.
|
||||
private final Set<DSpaceObject> toEvictFromManifestCache = new HashSet<>();
|
||||
|
||||
// Collects modified bitstreams for individual removal from canvas dimension cache.
|
||||
private final Set<DSpaceObject> toEvictFromCanvasCache = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void initialize() throws Exception {
|
||||
}
|
||||
@@ -44,7 +47,11 @@ public class IIIFCacheEventConsumer implements Consumer {
|
||||
if (!(st == Constants.BUNDLE || st == Constants.ITEM || st == Constants.BITSTREAM)) {
|
||||
return;
|
||||
}
|
||||
// This subject may become a reference to the parent Item that will be evicted from
|
||||
// the manifests cache.
|
||||
DSpaceObject subject = event.getSubject(ctx);
|
||||
DSpaceObject unmodifiedSubject = event.getSubject(ctx);
|
||||
|
||||
int et = event.getEventType();
|
||||
|
||||
if (et == Event.DELETE || et == Event.REMOVE) {
|
||||
@@ -95,43 +102,60 @@ public class IIIFCacheEventConsumer implements Consumer {
|
||||
|
||||
switch (et) {
|
||||
case Event.ADD:
|
||||
toEvictFromManifestCache.add(subject);
|
||||
addToCacheEviction(subject, unmodifiedSubject, st);
|
||||
break;
|
||||
case Event.MODIFY:
|
||||
toEvictFromManifestCache.add(subject);
|
||||
addToCacheEviction(subject, unmodifiedSubject, st);
|
||||
break;
|
||||
case Event.MODIFY_METADATA:
|
||||
toEvictFromManifestCache.add(subject);
|
||||
addToCacheEviction(subject, unmodifiedSubject, st);
|
||||
break;
|
||||
case Event.REMOVE:
|
||||
toEvictFromManifestCache.add(subject);
|
||||
addToCacheEviction(subject, unmodifiedSubject, st);
|
||||
break;
|
||||
case Event.DELETE:
|
||||
toEvictFromManifestCache.add(subject);
|
||||
addToCacheEviction(subject, unmodifiedSubject, st);
|
||||
break;
|
||||
default: {
|
||||
log.warn("IIIFCacheEventConsumer should not have been given this kind of "
|
||||
+ "subject in an event, skipping: " + event.toString());
|
||||
log.warn("ManifestsCacheEventConsumer should not have been given this kind of "
|
||||
+ "subject in an event, skipping: " + event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addToCacheEviction(DSpaceObject subject, DSpaceObject subject2, int type) {
|
||||
if (type == Constants.BITSTREAM) {
|
||||
toEvictFromCanvasCache.add(subject2);
|
||||
}
|
||||
toEvictFromManifestCache.add(subject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(Context ctx) throws Exception {
|
||||
// Gets the service bean.
|
||||
CacheEvictService cacheEvictService = CacheEvictBeanLocator.getCacheEvictService();
|
||||
if (cacheEvictService != null) {
|
||||
// Get the eviction service beans.
|
||||
ManifestsCacheEvictService manifestsCacheEvictService = CacheEvictBeanLocator.getManifestsCacheEvictService();
|
||||
CanvasCacheEvictService canvasCacheEvictService = CacheEvictBeanLocator.getCanvasCacheEvictService();
|
||||
|
||||
if (manifestsCacheEvictService != null) {
|
||||
if (clearAll) {
|
||||
cacheEvictService.evictAllCacheValues();
|
||||
manifestsCacheEvictService.evictAllCacheValues();
|
||||
} else {
|
||||
for (DSpaceObject dso : toEvictFromManifestCache) {
|
||||
UUID uuid = dso.getID();
|
||||
cacheEvictService.evictSingleCacheValue(uuid.toString());
|
||||
manifestsCacheEvictService.evictSingleCacheValue(uuid.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canvasCacheEvictService != null) {
|
||||
for (DSpaceObject dso : toEvictFromCanvasCache) {
|
||||
UUID uuid = dso.getID();
|
||||
canvasCacheEvictService.evictSingleCacheValue(uuid.toString());
|
||||
}
|
||||
}
|
||||
|
||||
clearAll = false;
|
||||
toEvictFromManifestCache.clear();
|
||||
toEvictFromCanvasCache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package org.dspace.iiif.consumer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -15,7 +17,7 @@ import org.springframework.stereotype.Component;
|
||||
* Removes items from the iiif manifests cache.
|
||||
*/
|
||||
@Component
|
||||
public class CacheEvictService {
|
||||
public class ManifestsCacheEvictService {
|
||||
|
||||
// The cache that is managed by this service.
|
||||
static final String CACHE_NAME = "manifests";
|
||||
@@ -24,11 +26,11 @@ public class CacheEvictService {
|
||||
CacheManager cacheManager;
|
||||
|
||||
public void evictSingleCacheValue(String cacheKey) {
|
||||
cacheManager.getCache(CACHE_NAME).evict(cacheKey);
|
||||
Objects.requireNonNull(cacheManager.getCache(CACHE_NAME)).evict(cacheKey);
|
||||
}
|
||||
|
||||
public void evictAllCacheValues() {
|
||||
cacheManager.getCache(CACHE_NAME).clear();
|
||||
Objects.requireNonNull(cacheManager.getCache(CACHE_NAME)).clear();
|
||||
}
|
||||
|
||||
}
|
@@ -45,6 +45,7 @@ public class IIIFSharedUtils {
|
||||
protected static final ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
|
||||
|
||||
private IIIFSharedUtils() {}
|
||||
|
||||
public static boolean isIIIFItem(Item item) {
|
||||
|
@@ -43,8 +43,8 @@ public abstract class AbstractResourceService {
|
||||
protected static final String THUMBNAIL_PATH = "/full/90,/0/default.jpg";
|
||||
protected static final String IMAGE_PATH = "/full/full/0/default.jpg";
|
||||
// Default canvas dimensions.
|
||||
protected static final Integer DEFAULT_CANVAS_WIDTH_FALLBACK = 1200;
|
||||
protected static final Integer DEFAULT_CANVAS_HEIGHT_FALLBACK = 1600;
|
||||
protected static Integer defaultCanvasWidthFallback = 2200;
|
||||
protected static Integer defaultCanvasHeightFallback = 1600;
|
||||
|
||||
@Autowired
|
||||
IIIFUtils utils;
|
||||
@@ -55,12 +55,15 @@ public abstract class AbstractResourceService {
|
||||
@Autowired
|
||||
ImageProfileUtil imageUtil;
|
||||
|
||||
ConfigurationService configurationService;
|
||||
|
||||
|
||||
/**
|
||||
* Set constants using DSpace configuration definitions.
|
||||
* @param configurationService the DSpace configuration service
|
||||
*/
|
||||
protected void setConfiguration(ConfigurationService configurationService) {
|
||||
this.configurationService = configurationService;
|
||||
IIIF_ENDPOINT = configurationService.getProperty("dspace.server.url") + "/iiif/";
|
||||
IMAGE_SERVICE = configurationService.getProperty("iiif.image.server");
|
||||
SEARCH_URL = configurationService.getProperty("iiif.search.url");
|
||||
@@ -68,10 +71,13 @@ public abstract class AbstractResourceService {
|
||||
DOCUMENT_VIEWING_HINT = configurationService.getProperty("iiif.document.viewing.hint");
|
||||
CLIENT_URL = configurationService.getProperty("dspace.ui.url");
|
||||
IIIF_LOGO_IMAGE = configurationService.getProperty("iiif.logo.image");
|
||||
DEFAULT_CANVAS_WIDTH = configurationService.getIntProperty("iiif.canvas.default-width",
|
||||
DEFAULT_CANVAS_WIDTH_FALLBACK);
|
||||
DEFAULT_CANVAS_HEIGHT = configurationService.getIntProperty("iiif.canvas.default-height",
|
||||
DEFAULT_CANVAS_HEIGHT_FALLBACK);
|
||||
}
|
||||
|
||||
protected void setDefaultCanvasDimensions() {
|
||||
DEFAULT_CANVAS_WIDTH = this.configurationService.getIntProperty("iiif.canvas.default-width",
|
||||
defaultCanvasWidthFallback);
|
||||
DEFAULT_CANVAS_HEIGHT = this.configurationService.getIntProperty("iiif.canvas.default-height",
|
||||
defaultCanvasHeightFallback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package org.dspace.app.iiif.service;
|
||||
|
||||
import static org.dspace.app.iiif.service.utils.IIIFUtils.METADATA_IMAGE_WIDTH;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -56,6 +58,13 @@ public class CanvasService extends AbstractResourceService {
|
||||
|
||||
protected String[] BITSTREAM_METADATA_FIELDS;
|
||||
|
||||
/**
|
||||
* Used when default dimensions are set to -1 in configuration.
|
||||
*/
|
||||
int dynamicDefaultWidth = 0;
|
||||
int dynamicDefaultHeight = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -64,6 +73,79 @@ public class CanvasService extends AbstractResourceService {
|
||||
public CanvasService(ConfigurationService configurationService) {
|
||||
setConfiguration(configurationService);
|
||||
BITSTREAM_METADATA_FIELDS = configurationService.getArrayProperty("iiif.metadata.bitstream");
|
||||
// Set default dimensions in parent class.
|
||||
setDefaultCanvasDimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for bitstream iiif.image.width metadata in the first
|
||||
* bitstream in first IIIF bundle. If bitstream metadata is not
|
||||
* found, use the IIIF image service to update the default canvas
|
||||
* dimensions for this request. Called once for each manifest.
|
||||
* @param bundles IIIF bundles for this item
|
||||
*/
|
||||
protected void guessCanvasDimensions(List<Bundle> bundles) {
|
||||
Bitstream firstBistream = bundles.get(0).getBitstreams().get(0);
|
||||
if (!utils.hasWidthMetadata(firstBistream)) {
|
||||
int[] imageDims = utils.getImageDimensions(firstBistream);
|
||||
if (imageDims != null && imageDims.length == 2) {
|
||||
// update the fallback dimensions
|
||||
defaultCanvasWidthFallback = imageDims[0];
|
||||
defaultCanvasHeightFallback = imageDims[1];
|
||||
}
|
||||
setDefaultCanvasDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set the height and width dimensions for all images when iiif.image.default-width and
|
||||
* iiif.image.default-height are set to -1 in DSpace configuration.
|
||||
* The values are updated only if the bitstream does not have its own iiif.image.width metadata.
|
||||
* @param bitstream
|
||||
*/
|
||||
private void setCanvasDimensions(Bitstream bitstream) {
|
||||
if (DEFAULT_CANVAS_HEIGHT == -1 && DEFAULT_CANVAS_WIDTH == -1) {
|
||||
// When the default dimension is -1, update default dimensions when the
|
||||
// image has no width metadata.
|
||||
if (bitstream.getMetadata().stream().noneMatch(m -> m.getMetadataField().toString('.')
|
||||
.contentEquals(METADATA_IMAGE_WIDTH))) {
|
||||
int[] imageDims = utils.getImageDimensions(bitstream);
|
||||
if (imageDims != null && imageDims.length == 2) {
|
||||
// update the dynamic default dimensions for this bitstream
|
||||
dynamicDefaultWidth = imageDims[0];
|
||||
dynamicDefaultHeight = imageDims[1];
|
||||
}
|
||||
if (imageDims == null) {
|
||||
// use fallback.
|
||||
dynamicDefaultWidth = defaultCanvasWidthFallback;
|
||||
dynamicDefaultHeight = defaultCanvasHeightFallback;
|
||||
log.error("Unable to retrieve dimensions from the image server for: " + bitstream.getID() +
|
||||
" Using default dimensions.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the dynamic default if the configured default width is -1.
|
||||
* @return
|
||||
*/
|
||||
private int getDefaultWidth() {
|
||||
if (DEFAULT_CANVAS_WIDTH == -1) {
|
||||
return dynamicDefaultWidth;
|
||||
}
|
||||
return DEFAULT_CANVAS_WIDTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the dynamic default if the configured default height is -1.
|
||||
* @return
|
||||
*/
|
||||
private int getDefaultHeight() {
|
||||
if (DEFAULT_CANVAS_HEIGHT == -1) {
|
||||
return dynamicDefaultHeight;
|
||||
}
|
||||
return DEFAULT_CANVAS_HEIGHT;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,10 +166,12 @@ public class CanvasService extends AbstractResourceService {
|
||||
|
||||
String canvasNaming = utils.getCanvasNaming(item, I18nUtil.getMessage("iiif.canvas.default-naming"));
|
||||
String label = utils.getIIIFLabel(bitstream, canvasNaming + " " + pagePosition);
|
||||
int canvasWidth = utils.getCanvasWidth(bitstream, bundle, item, DEFAULT_CANVAS_WIDTH);
|
||||
int canvasHeight = utils.getCanvasHeight(bitstream, bundle, item, DEFAULT_CANVAS_HEIGHT);
|
||||
UUID bitstreamId = bitstream.getID();
|
||||
|
||||
setCanvasDimensions(bitstream);
|
||||
|
||||
int canvasWidth = utils.getCanvasWidth(bitstream, bundle, item, getDefaultWidth());
|
||||
int canvasHeight = utils.getCanvasHeight(bitstream, bundle, item, getDefaultHeight());
|
||||
UUID bitstreamId = bitstream.getID();
|
||||
ImageContentGenerator image = imageContentService.getImageContent(bitstreamId, mimeType,
|
||||
imageUtil.getImageProfile(), IMAGE_PATH);
|
||||
|
||||
|
@@ -85,6 +85,12 @@ public class ManifestService extends AbstractResourceService {
|
||||
MetadataExposureService metadataExposureService;
|
||||
|
||||
protected String[] METADATA_FIELDS;
|
||||
|
||||
/**
|
||||
* Estimate image dimension metadata.
|
||||
*/
|
||||
boolean guessCanvasDimension;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param configurationService the DSpace configuration service.
|
||||
@@ -102,6 +108,10 @@ public class ManifestService extends AbstractResourceService {
|
||||
* @return manifest as JSON
|
||||
*/
|
||||
public String getManifest(Item item, Context context) {
|
||||
// If default dimensions are provided via configuration do not guess the default dimension.
|
||||
String wid = configurationService.getProperty("iiif.canvas.default-width");
|
||||
String hgt = configurationService.getProperty("iiif.canvas.default-height");
|
||||
guessCanvasDimension = (wid == null && hgt == null);
|
||||
populateManifest(item, context);
|
||||
return utils.asJson(manifestGenerator.generateResource());
|
||||
}
|
||||
@@ -131,9 +141,9 @@ public class ManifestService extends AbstractResourceService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Canvases and Ranges to the manifest. Ranges are generated from bitstream
|
||||
* or bundle iiif metadata.
|
||||
*
|
||||
* Add the ranges to the manifest structure. Ranges are generated from the
|
||||
* iiif.toc metadata
|
||||
*
|
||||
* @param context the DSpace Context
|
||||
* @param item the DSpace Item to represent
|
||||
* @param manifestId the generated manifestId
|
||||
@@ -142,8 +152,13 @@ public class ManifestService extends AbstractResourceService {
|
||||
|
||||
// Set the root Range for this manifest.
|
||||
rangeService.setRootRange(manifestId);
|
||||
// Get bundles that can contain IIIF manifest data.
|
||||
// Get bundles that contain manifest data.
|
||||
List<Bundle> bundles = utils.getIIIFBundles(item);
|
||||
// Set the default canvas dimensions.
|
||||
if (guessCanvasDimension) {
|
||||
canvasService.guessCanvasDimensions(bundles);
|
||||
}
|
||||
// canvasService.setDefaultCanvasDimensions();
|
||||
for (Bundle bnd : bundles) {
|
||||
String bundleToCPrefix = null;
|
||||
if (bundles.size() > 1) {
|
||||
@@ -151,13 +166,13 @@ public class ManifestService extends AbstractResourceService {
|
||||
bundleToCPrefix = utils.getBundleIIIFToC(bnd);
|
||||
}
|
||||
for (Bitstream bitstream : utils.getIIIFBitstreams(context, bnd)) {
|
||||
// Add the Canvas to the manifest Sequence.
|
||||
// Add the Canvas to the Sequence.
|
||||
CanvasGenerator canvas = sequenceService.addCanvas(context, item, bnd, bitstream);
|
||||
// Update the Ranges.
|
||||
rangeService.updateRanges(bitstream, bundleToCPrefix, canvas);
|
||||
}
|
||||
}
|
||||
// If Ranges were created, add them to manifest Structures element.
|
||||
// If Ranges were created, add them to manifest.
|
||||
Map<String, RangeGenerator> tocRanges = rangeService.getTocRanges();
|
||||
if (tocRanges != null && tocRanges.size() > 0) {
|
||||
RangeGenerator rootRange = rangeService.getRootRange();
|
||||
|
@@ -33,8 +33,11 @@ import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataValue;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.iiif.IIIFApiQueryService;
|
||||
import org.dspace.iiif.util.IIIFSharedUtils;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@@ -82,6 +85,12 @@ public class IIIFUtils {
|
||||
@Autowired
|
||||
protected BitstreamService bitstreamService;
|
||||
|
||||
@Autowired
|
||||
ConfigurationService configurationService;
|
||||
|
||||
@Autowired
|
||||
IIIFApiQueryService iiifApiQueryService;
|
||||
|
||||
|
||||
public List<Bundle> getIIIFBundles(Item item) {
|
||||
return IIIFSharedUtils.getIIIFBundles(item);
|
||||
@@ -93,7 +102,7 @@ public class IIIFUtils {
|
||||
|
||||
/**
|
||||
* Return all the bitstreams in the item to be used as IIIF resources
|
||||
*
|
||||
*
|
||||
* @param context the DSpace Context
|
||||
* @param item the DSpace item
|
||||
* @return a not null list of bitstreams to use as IIIF resources in the
|
||||
@@ -110,7 +119,7 @@ public class IIIFUtils {
|
||||
|
||||
/**
|
||||
* Return all the bitstreams in the bundle to be used as IIIF resources
|
||||
*
|
||||
*
|
||||
* @param context the DSpace Context
|
||||
* @param bundle the DSpace Bundle
|
||||
* @return a not null list of bitstreams to use as IIIF resources in the
|
||||
@@ -123,7 +132,7 @@ public class IIIFUtils {
|
||||
|
||||
/**
|
||||
* Utility method to check is a bitstream can be used as IIIF resources
|
||||
*
|
||||
*
|
||||
* @param b the DSpace bitstream to check
|
||||
* @return true if the bitstream can be used as IIIF resource
|
||||
*/
|
||||
@@ -135,7 +144,7 @@ public class IIIFUtils {
|
||||
|
||||
/**
|
||||
* Returns the bitstream mime type
|
||||
*
|
||||
*
|
||||
* @param bitstream DSpace bitstream
|
||||
* @param context DSpace context
|
||||
* @return mime type
|
||||
@@ -153,7 +162,7 @@ public class IIIFUtils {
|
||||
/**
|
||||
* Checks to see if the item is searchable. Based on the
|
||||
* {@link #METADATA_IIIF_SEARCH_ENABLED} metadata.
|
||||
*
|
||||
*
|
||||
* @param item DSpace item
|
||||
* @return true if the iiif search is enabled
|
||||
*/
|
||||
@@ -166,7 +175,7 @@ public class IIIFUtils {
|
||||
|
||||
/**
|
||||
* Retrives a bitstream based on its position in the IIIF bundle.
|
||||
*
|
||||
*
|
||||
* @param context DSpace Context
|
||||
* @param item DSpace Item
|
||||
* @param canvasPosition bitstream position
|
||||
@@ -246,7 +255,7 @@ public class IIIFUtils {
|
||||
|
||||
/**
|
||||
* Return the custom iiif label for the resource or the provided default if none
|
||||
*
|
||||
*
|
||||
* @param dso the dspace object to use as iiif resource
|
||||
* @param defaultLabel the default label to return if none is specified in the
|
||||
* metadata
|
||||
@@ -260,7 +269,7 @@ public class IIIFUtils {
|
||||
|
||||
/**
|
||||
* Return the custom iiif description for the resource or the provided default if none
|
||||
*
|
||||
*
|
||||
* @param dso the dspace object to use as iiif resource
|
||||
* @param defaultDescription the default description to return if none is specified in the
|
||||
* metadata
|
||||
@@ -277,7 +286,7 @@ public class IIIFUtils {
|
||||
* resource appears. Please note that the same resource can belong to multiple
|
||||
* ranges (i.e. a page that contains the last paragraph of a section and start
|
||||
* the new section)
|
||||
*
|
||||
*
|
||||
* @param bitstream the dspace bitstream
|
||||
* @param prefix a string to add to all the returned toc inherited from the
|
||||
* parent dspace object
|
||||
@@ -295,6 +304,28 @@ public class IIIFUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves image dimensions from the image server (IIIF Image API v.2.1.1).
|
||||
* @param bitstream the bitstream DSO
|
||||
* @return image dimensions
|
||||
*/
|
||||
@Cacheable(key = "#bitstream.getID().toString()", cacheNames = "canvasdimensions")
|
||||
public int[] getImageDimensions(Bitstream bitstream) {
|
||||
return iiifApiQueryService.getImageDimensions(bitstream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the bitstream contains iiif image width metadata.
|
||||
* @param bitstream the bitstream DSo
|
||||
* @return true if width metadata was found
|
||||
*/
|
||||
public boolean hasWidthMetadata(Bitstream bitstream) {
|
||||
return bitstream.getMetadata().stream()
|
||||
.filter(m -> m.getMetadataField().toString('.').contentEquals("iiif.image.width"))
|
||||
.findFirst().map(m -> m != null).orElse(false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the iiif toc for the specified bundle
|
||||
*
|
||||
@@ -373,7 +404,8 @@ public class IIIFUtils {
|
||||
private int getSizeFromMetadata(DSpaceObject dso, String metadata, int defaultValue) {
|
||||
return dso.getMetadata().stream()
|
||||
.filter(m -> m.getMetadataField().toString('.').contentEquals(metadata))
|
||||
.findFirst().map(m -> castToInt(m, defaultValue)).orElse(defaultValue);
|
||||
.findFirst().map(m -> castToInt(m, defaultValue))
|
||||
.orElse(defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -18,7 +18,7 @@ public class CacheLogger implements CacheEventListener<Object, Object> {
|
||||
|
||||
@Override
|
||||
public void onEvent(CacheEvent<?, ?> cacheEvent) {
|
||||
log.info("Cache Event Type: {} | Manifest Key: {} ",
|
||||
log.info("Cache Event Type: {} | Key: {} ",
|
||||
cacheEvent.getType(), cacheEvent.getKey());
|
||||
}
|
||||
|
||||
|
24
dspace-server-webapp/src/main/java/org/dspace/app/rest/cache/CanvasCacheLogger.java
vendored
Normal file
24
dspace-server-webapp/src/main/java/org/dspace/app/rest/cache/CanvasCacheLogger.java
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.cache;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.ehcache.event.CacheEvent;
|
||||
import org.ehcache.event.CacheEventListener;
|
||||
|
||||
public class CanvasCacheLogger implements CacheEventListener<Object, Object> {
|
||||
private static final Logger log = LogManager.getLogger(CacheLogger.class);
|
||||
|
||||
@Override
|
||||
public void onEvent(CacheEvent<?, ?> cacheEvent) {
|
||||
log.info("Canvas Dimension Cache Event Type: {} | Key: {} ",
|
||||
cacheEvent.getType(), cacheEvent.getKey());
|
||||
}
|
||||
|
||||
}
|
@@ -21,6 +21,7 @@
|
||||
<event-ordering-mode>UNORDERED</event-ordering-mode>
|
||||
<events-to-fire-on>CREATED</events-to-fire-on>
|
||||
<events-to-fire-on>EXPIRED</events-to-fire-on>
|
||||
<events-to-fire-on>REMOVED</events-to-fire-on>
|
||||
<events-to-fire-on>EVICTED</events-to-fire-on>
|
||||
</listener>
|
||||
</listeners>
|
||||
@@ -29,6 +30,23 @@
|
||||
<offheap unit="MB">10</offheap>
|
||||
</resources>
|
||||
</cache-template>
|
||||
<cache alias="manifests" uses-template="iiif-default">
|
||||
</cache>
|
||||
<cache-template name="iiif-canvas">
|
||||
<listeners>
|
||||
<listener>
|
||||
<class>org.dspace.app.rest.cache.CanvasCacheLogger</class>
|
||||
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
|
||||
<event-ordering-mode>UNORDERED</event-ordering-mode>
|
||||
<events-to-fire-on>CREATED</events-to-fire-on>
|
||||
<events-to-fire-on>EXPIRED</events-to-fire-on>
|
||||
<events-to-fire-on>REMOVED</events-to-fire-on>
|
||||
<events-to-fire-on>EVICTED</events-to-fire-on>
|
||||
</listener>
|
||||
</listeners>
|
||||
<resources>
|
||||
<heap>3000</heap>
|
||||
<offheap unit="MB">4</offheap>
|
||||
</resources>
|
||||
</cache-template>
|
||||
<cache alias="manifests" uses-template="iiif-default"/>
|
||||
<cache alias="canvasdimensions" uses-template="iiif-canvas"/>
|
||||
</config>
|
||||
|
@@ -134,7 +134,7 @@ public class IIIFControllerIT extends AbstractControllerIntegrationTest {
|
||||
.andExpect(jsonPath("$.sequences[0].canvases[0].@id",
|
||||
Matchers.containsString("/iiif/" + publicItem1.getID() + "/canvas/c0")))
|
||||
.andExpect(jsonPath("$.sequences[0].canvases[0].label", is("Page 1")))
|
||||
.andExpect(jsonPath("$.sequences[0].canvases[0].width", is(1200)))
|
||||
.andExpect(jsonPath("$.sequences[0].canvases[0].width", is(2200)))
|
||||
.andExpect(jsonPath("$.sequences[0].canvases[0].images[0].resource.service.@id",
|
||||
Matchers.endsWith(bitstream1.getID().toString())))
|
||||
.andExpect(jsonPath("$.sequences[0].canvases[0].metadata[0].label", is("File name")))
|
||||
|
@@ -78,6 +78,10 @@ iiif.logo.image = ${dspace.ui.url}/assets/images/dspace-logo.svg
|
||||
iiif.document.viewing.hint = individuals
|
||||
|
||||
# default value for the canvas size. Can be overridden at the item, bundle or bitstream level
|
||||
# via the iiif.image.width e iiif.image.height metadata
|
||||
# iiif.canvas.default-width = 1200
|
||||
# via the iiif.image.width and iiif.image.height metadata.
|
||||
# If you want DSpace to retrieve accurate default dimensions for all images that lack height and width metadata,
|
||||
# set both values to be -1. These lookups can be expensive, so it's always best to update your bitstream
|
||||
# metadata with accurate iiif height and width dimensions for each image as soon as possible.
|
||||
# iiif.canvas.default-width = 2200
|
||||
# iiif.canvas.default-height = 1600
|
||||
|
||||
|
@@ -5,6 +5,6 @@
|
||||
|
||||
<bean id="iiifCanvasDimensionServiceFactory" class="org.dspace.iiif.canvasdimension.factory.IIIFCanvasDimensionServiceFactoryImpl"/>
|
||||
<bean class="org.dspace.iiif.canvasdimension.IIIFCanvasDimensionServiceImpl" scope="prototype"/>
|
||||
<bean class="org.dspace.iiif.IIIFApiQueryServiceImpl" scope="prototype"/>
|
||||
<bean class="org.dspace.iiif.IIIFApiQueryServiceImpl"/>
|
||||
|
||||
</beans>
|
||||
|
Reference in New Issue
Block a user