/*
* Copyright (C) 2015 Patryk Strach
*
* This file is part of Virtual Slide Viewer.
*
* Virtual Slide Viewer is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* Virtual Slide Viewer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Virtual Slide Viewer.
* If not, see <http://www.gnu.org/licenses/>.
*/
package virtualslideviewer;
import java.io.Serializable;
import java.util.NoSuchElementException;
import virtualslideviewer.core.Tile;
import virtualslideviewer.core.TileCache;
import virtualslideviewer.core.VirtualSlideImage;
import virtualslideviewer.util.ParameterValidator;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
/**
* Adapter for TileCache interface for ehcache library.
*/
public class EhcacheTileCacheAdapter implements TileCache
{
private final Ehcache mCache;
/**
* @param cache Cache to use for storing tiles.
*/
public EhcacheTileCacheAdapter(Ehcache cache)
{
ParameterValidator.throwIfNull(cache, "cache");
mCache = cache;
}
@Override
public void addTile(VirtualSlideImage image, Tile tile, byte[] tileData)
{
ParameterValidator.throwIfNull(image, "image");
ParameterValidator.throwIfNull(tile, "tile");
ParameterValidator.throwIfNull(tileData, "tileData");
// Adding to cache should not update access statistics.
// It is needed in prefetching to prevent situation when prefetching removes just loaded tiles in very low memory situation.
// mCache.putQuiet(new Element(new UniqueTileID(image.getID(), tile), tileData));
// TODO That's not good either... putQuiet also causes problems when loading the tile.
// When the cache is full there are temporary artifacts during loading if using putQuiet().
// Probably different call will have to be used in the case of loading and different when prefetching.
mCache.put(new Element(new UniqueTileID(image.getID(), tile), tileData));
}
@Override
public boolean hasTile(VirtualSlideImage image, Tile tile)
{
ParameterValidator.throwIfNull(image, "image");
ParameterValidator.throwIfNull(tile, "tile");
return mCache.isKeyInCache(new UniqueTileID(image.getID(), tile));
}
@Override
public byte[] getTileData(VirtualSlideImage image, Tile tile) throws NoSuchElementException
{
if(!hasTile(image, tile))
throw new NoSuchElementException(tile + " of \"" + image + "\" is not in cache.");
return (byte[])mCache.get(new UniqueTileID(image.getID(), tile)).getObjectValue();
}
@Override
public void clear()
{
mCache.removeAll();
}
/**
* Tile ID unique to given image.
*
* Tile with the same coordinates in two different images has different unique ID.
*/
private static class UniqueTileID implements Serializable
{
private static final long serialVersionUID = -8405926210569156066L;
private final String mImageID;
private final Tile mTile;
public UniqueTileID(String imageID, Tile tile)
{
mImageID = imageID;
mTile = tile;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + mImageID.hashCode();
result = prime * result + mTile.hashCode();
return result;
}
@Override
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
UniqueTileID other = (UniqueTileID)obj;
return mTile.equals(other.mTile) && mImageID.equals(other.mImageID);
}
}
}