Merge pull request #8047 from mspalti/dynamic-default-dims

Dynamic IIIF canvas dimensions
This commit is contained in:
Tim Donohue
2022-02-01 09:58:14 -06:00
committed by GitHub
16 changed files with 298 additions and 60 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -45,6 +45,7 @@ public class IIIFSharedUtils {
protected static final ConfigurationService configurationService
= DSpaceServicesFactory.getInstance().getConfigurationService();
private IIIFSharedUtils() {}
public static boolean isIIIFItem(Item item) {

View File

@@ -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);
}
/**

View File

@@ -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);

View File

@@ -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();

View File

@@ -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);
}
/**

View File

@@ -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());
}

View 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());
}
}

View File

@@ -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>

View File

@@ -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")))

View File

@@ -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

View File

@@ -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>